Symbian3/SDK/Source/GUID-43080A86-72D3-5422-953E-A5EF79961D7B.dita
changeset 7 51a74ef9ed63
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Symbian3/SDK/Source/GUID-43080A86-72D3-5422-953E-A5EF79961D7B.dita	Wed Mar 31 11:11:55 2010 +0100
@@ -0,0 +1,350 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
+<!-- This component and the accompanying materials are made available under the terms of the License 
+"Eclipse Public License v1.0" which accompanies this distribution, 
+and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
+<!-- Initial Contributors:
+    Nokia Corporation - initial contribution.
+Contributors: 
+-->
+<!DOCTYPE concept
+  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
+<concept id="GUID-43080A86-72D3-5422-953E-A5EF79961D7B" xml:lang="en"><title>Writing
+a UPS Policy Evaluator</title><prolog><metadata><keywords/></metadata></prolog><conbody>
+<section id="GUID-56EDF170-1A32-4275-8799-99D13C485E1E"><title>Introduction</title> <p>Policy Evaluators are ECOM plug-ins.
+They allow security decisions to be specific to the data on which the service
+acts instead of simply granting full access to the service, for example "Allow
+application X to send SMS messages to 01234567". This is supported through
+the fingerprint functionality. They allow a security decision to be specific
+to an individual script executing within a scripting host. This is supported
+through the client entity field. And they allow a prompt to be displayed even
+if the user selected "Always" or "Never". This could be based on a usage threshold
+or simply as additional confirmation if the user selected "Never". This is
+supported through the force prompt functionality. </p> <p> <b>Note</b>: when
+a user selects “Never” or “Always”, the UPS creates a record in a decision
+database. This record identifies the system server UID, service UID, client
+SID, client entity name (name of an entity running within a client process,
+for example, a script identifier) and a "fingerprint" for a given decision. </p> <p>The
+purpose of a Policy Evaluator is to allow device creators to optionally customise
+the behaviour of the UPS at run-time. Policy Evaluators may: </p> <ul>
+<li id="GUID-1D5DD614-02E3-56AA-A0A6-A694E2311A0E"><p>Allow security decisions
+to be specific to the data on which the service acts instead of simply granting
+full access to the service, for example "Allow application X to send SMS messages
+to 01234567". This is supported via the fingerprint functionality. </p> </li>
+<li id="GUID-5B5E3EB4-5C93-5E4E-BB6E-39F889AD3610"><p>Allow a security decision
+to be specific to an individual script executing within a scripting host.
+This is supported via the client entity field. </p> </li>
+<li id="GUID-8B26DA57-A9DF-5D99-A259-2E6DF7C4DCCE"><p>Allow a prompt to be
+displayed even if the user selected "Always" or "Never". This could be based
+on a usage threshold or simply as additional confirmation if the user selected
+"Never". This is supported via the force prompt functionality. </p> </li>
+</ul> </section>
+<section id="GUID-CCBB139D-0F1C-4AD4-B2F2-062CF660A0DE"><title>Procedure</title> <p>Writing policy evaluator includes the
+following: </p> <ol id="GUID-F50174F6-3619-545A-8844-D4DA64B1B339">
+<li id="GUID-246EF2AB-23D9-5B1B-BC4C-8CCFB545C307"><p>Generating fingerprints </p> </li>
+<li id="GUID-4427FF70-9461-566A-8567-FC6EEF879475"><p>Forcing prompts </p> </li>
+<li id="GUID-703D9B83-78A0-5EA6-8D1C-685D2BC847EA"><p>Defining default policy
+evaluator </p> </li>
+</ol> <p>Policy evaluators implement the <codeph>CPolicyEvaluator</codeph> interface. </p> <p><b>Generating
+fingerprints</b> </p> <p>The key task of the policy evaluator is to generate
+fingerprints. A fingerprint is a collection of data describing the service
+being requested. The fingerprint usually includes the <codeph>destination</codeph> string,
+for example a telephone number, supplied by the service that is matched to
+the <codeph>destination</codeph> string of a policy in the policy file. </p> <p>The
+policy evaluator must implement the <codeph>GenerateFingerprints()</codeph> function,
+which is a pure virtual function, declared in the <xref href="GUID-FDE91CAC-1588-3EED-B509-08168F4B881B.dita"><apiname>CPolicyEvaluator</apiname></xref> base
+class. The function is asynchronous to allow the implementation to call other
+server processes. </p> <p>The following table describes the parameters for
+the <codeph>GenerateFingerprints()</codeph> function: </p> <table id="GUID-963D89B8-EB90-5668-8A08-588EF1E94C43">
+<tgroup cols="2"><colspec colname="col0"/><colspec colname="col1"/>
+<thead>
+<row>
+<entry>Parameter</entry>
+<entry>Description</entry>
+</row>
+</thead>
+<tbody>
+<row>
+<entry><p> <codeph>aRequest</codeph>  </p> </entry>
+<entry><p>Data that the system server provides to the UPS, including the ClientSid,
+ServerSid and ServiceId. </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>aPolicy</codeph>  </p> </entry>
+<entry><p>Details of the policy for the service. </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>aFingerprints</codeph>  </p> </entry>
+<entry><p>Array of fingerprints. </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>aClientEntity</codeph>  </p> </entry>
+<entry><p>Details of client entity (will be null if the client process is
+not an execution host or the policy evaluator does not support client entities). </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>aDialogCreatorParams</codeph>  </p> </entry>
+<entry><p>Opaque data, which can be any other information for use in the fingerprint
+or to be displayed in the dialog. </p> </entry>
+</row>
+<row>
+<entry><p> <codeph>aStatus</codeph>  </p> </entry>
+<entry><p>The request status used to contain completion information for the
+function. </p> </entry>
+</row>
+</tbody>
+</tgroup>
+</table> <p>The following code fragment is a sample implementation of the <codeph>GenerateFingerprints()</codeph> function. </p> <codeblock id="GUID-B8555FDF-8BDD-5D22-AA20-AA9A4B35148A" xml:space="preserve">void CRefPolicyEvaluator::GenerateFingerprints(
+ const CPromptRequest&amp; aRequest, const CPolicy&amp; aPolicy, 
+    RPointerArray&lt;CFingerprint&gt;&amp; aFingerprints, const CClientEntity*&amp; aClientEntity, 
+    const TAny*&amp; aDialogCreatorParams, TRequestStatus&amp; aStatus)
+    {
+    iRequest = &amp;aRequest;
+    iPolicy = &amp;aPolicy;
+    iFingerprints = &amp;aFingerprints;        
+
+    // This OUT parameter *could* be set to point to data structure
+    // owned by this policy evaluator that is read by the dialog-creator.
+    aDialogCreatorParams = 0;
+    
+    // The client entity field only needs to be set if the policy evaluator
+    // is designed to identify scripts/non-native applications being executed
+    // by the client application.
+    aClientEntity = 0;                
+    
+    iClientStatus = &amp;aStatus;
+    aStatus = KRequestPending;
+    
+    // Kick off policy evaluator state machine
+    iStatus = KRequestPending;
+    TRequestStatus* status = &amp;iStatus;
+    SetActive();
+    User::RequestComplete(status, KErrNone);
+    }
+</codeblock> <p> <codeph>RunL()</codeph> is called when the request completes.
+The fingerprint is created and appended to the fingerprint array in <codeph>RunL()</codeph>.
+The following example shows a hash of a destination being created for a fingerprint
+as well as an empty fingerprint for decisions that apply to all destinations. </p> <codeblock id="GUID-EB57F6E0-C3B2-5CDC-B9FF-A570B73B4C74" xml:space="preserve">void CRefPolicyEvaluator::RunL()
+    {    
+    // Create most specific hash first i.e. HASH(destination)
+    // Information from the opaque data supplied by the system server 
+    // may also be used.
+    // N.B. The UPS does not require the fingerprint to be a hash. However,
+    // the fingerprint is limited to 32 bytes.    
+    iDigest-&gt;Reset();
+    const TDesC&amp; d = iRequest-&gt;Destination();
+    TPtrC8 p(reinterpret_cast&lt;const TUint8*&gt;(d.Ptr()), d.Length() * 2);
+    TPtrC8 h(iDigest-&gt;Hash(p));
+    
+    CFingerprint* f = CFingerprint::NewLC(h, d);
+    iFingerprints-&gt;AppendL(f);
+    CleanupStack::Pop(f);
+
+    // An empty fingerprint may be used for decisions that apply to
+    // all destinations.
+    f = CFingerprint::NewLC(KNullDesC8, KNullDesC);
+    iFingerprints-&gt;AppendL(f);
+    CleanupStack::Pop(f);
+        
+    User::RequestComplete(iClientStatus, KErrNone);
+    }
+</codeblock> <p><b>Forcing prompts</b> </p> <p>You can implement the <codeph>ForcePromptL()</codeph> function
+to force a prompt, even if the UPS has found a persistent decision for the
+request in the decision database. It may be desirable to force a prompt in
+some cases such as: </p> <ul>
+<li id="GUID-4C9DDFB3-C358-534F-8E65-42E1BC672D64"><p>if a threshold has been
+reached, for example the number of MMS messages sent on a particular day </p> </li>
+<li id="GUID-5D5E02E5-DA19-5A30-8071-CD64631FBEAD"><p>if a phone user has
+selected "Never", because denying a request to a non-UPS-aware application
+may cause it to fail — the user may not realise that the previous selection
+of "Never" has caused the failure or may not know how to find the management
+application to revert the decision </p> </li>
+</ul> <p>The UPS invokes the <codeph>ForcePromptL()</codeph> function after
+a matching record is found in the database. The <codeph>ForcePromptL()</codeph> function
+is defined in the <codeph>CPolicyEvaluator</codeph> base class. The implementation
+in the base class always returns <codeph>EFalse</codeph>. To force a prompt,
+device creators need to override this function and return <codeph>ETrue</codeph>.
+A sample implementation is as follows. The <codeph>aNewEvaluatorInfo</codeph> field
+is a policy evaluator defined 32-bit field. It could be used to store usage
+thresholds or as a flag that indicates that the prompt has already been forced. </p> <codeblock id="GUID-4E60DCA5-7F25-5FC7-B173-05E1A15FCEE6" xml:space="preserve">TBool CRefPolicyEvaluator::ForcePromptL(const CDecisionRecord&amp; aDecision, TUint&amp; aNewEvaluatorInfo)
+    {
+    // In this example, if the user selects Never, then they are prompted
+    // once more in-case they did not intend to select Never. 
+    // The "Evaluator Info" field is used to ensure the prompt is only forced once.
+    //
+    // The base class implementation (CPolicyEvaluator::ForcePromptL) 
+    // always returns EFalse.
+    aNewEvaluatorInfo = 1;
+    return (aDecision.iResult == 0 &amp;&amp; aDecision.iEvaluatorInfo == 0);
+    }
+</codeblock> <p><b>Defining default policy evaluator</b> </p> <p>If device
+creators do not define a policy evaluator, a default (internal) policy evaluator
+is returned. The default policy evaluator returns a single, null fingerprint.
+The default policy evaluator does not override the <codeph>ForcePromptL()</codeph> API. </p> </section>
+<section id="GUID-987ECDA9-5728-4A7A-AB38-D58A7CC097AC"><title> Upgrading policy evaluators </title> <p>A policy evaluator
+can be overwritten or eclipsed without restarting the UPS, if it is delivered
+through an appropriately signed upgrade. </p> <ul>
+<li id="GUID-086FABB6-13C0-5D98-8B2A-1D38BD620EB5"><p>The ECOM plug-in will
+be reloaded only when there are no active <codeph>RUpsSubsession::Authorise()</codeph> requests. </p> </li>
+<li id="GUID-CD95EB32-9438-5AA1-BA80-8C90DC304642"><p>The decision records
+are not deleted if the policy evaluator is changed. If the policy evaluator
+is not backwards compatible then new policy files with a new <codeph>majorversion</codeph> number
+should be delivered. </p> </li>
+<li id="GUID-DC1804B8-A052-52AC-96DC-32C3BBADE2A8"><p>SWI Observer informs
+the UPS that the plug-ins may have changed whenever Software Install modifies <filepath>sys\bin</filepath> on
+the system drive. There is no need to explicitly register changes to plug-ins. </p> </li>
+</ul> </section>
+<section id="GUID-48624948-C1C9-4DEA-A6E1-6E4B9AC72E8E"><title> Policy evaluator example</title> <p>The following code shows
+an example of a full implementation of the policy evaluator file: </p> <codeblock id="GUID-D1615A8D-334C-5718-BFD6-EC3004A09F3A" xml:space="preserve">#include "refpolicyevaluator.h"
+#include &lt;ecom/implementationproxy.h&gt;
+#include &lt;ups/cliententity.h&gt;
+#include &lt;ups/fingerprint.h&gt;
+#include &lt;ups/upsdb.h&gt;
+
+using namespace UserPromptService;
+
+static const TUint KRefPolicyEvaluatorImplementationId = 0x10285814;
+
+CPolicyEvaluator* CRefPolicyEvaluator::CreatePolicyEvaluatorL()
+/**
+Factory method that instantiates a new policy evaluator ECOM plug-in.
+
+@return A pointer to the new reference policy evaluator object.
+*/
+    {
+    CRefPolicyEvaluator* self = new (ELeave)CRefPolicyEvaluator();
+    CleanupStack::PushL(self);
+    self-&gt;ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+static const TImplementationProxy ImplementationTable[] = 
+    {
+    IMPLEMENTATION_PROXY_ENTRY(KRefPolicyEvaluatorImplementationId, CRefPolicyEvaluator::CreatePolicyEvaluatorL)
+    };
+
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt&amp; aTableCount)
+/**
+Standard ECOM factory
+*/
+    {
+    aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
+    return ImplementationTable;
+    }    
+    
+
+CRefPolicyEvaluator::CRefPolicyEvaluator()
+/**
+Constructor
+*/
+    : CPolicyEvaluator()
+    {
+    CActiveScheduler::Add(this);
+    }
+    
+CRefPolicyEvaluator::~CRefPolicyEvaluator()
+/**
+Destructor
+*/
+    {
+    Deque();
+    delete iDigest;
+    }
+
+void CRefPolicyEvaluator::ConstructL()
+/**
+Second phase constructor, creates the message digest
+*/
+    {    
+    iDigest = CMessageDigestFactory::NewDigestL(CMessageDigest::EMD5);
+    }
+
+// From CActive
+void CRefPolicyEvaluator::DoCancel()
+    {    
+    // Logically should Cancel the internal outstanding requst, but
+    // currently GenerateFingerprints has already completed it.
+
+    // And need to complete the clients request
+    if (iClientStatus)
+        {
+        User::RequestComplete(iClientStatus, KErrCancel);
+        }
+    }
+    
+TInt CRefPolicyEvaluator::RunError(TInt aError)
+    {
+    if (iClientStatus)
+        {
+        User::RequestComplete(iClientStatus, aError);
+        }
+    return KErrNone;
+    }
+    
+void CRefPolicyEvaluator::RunL()
+    {    
+    // Create most specific hash first i.e. HASH(destination)
+    // Information from the opaque data supplied by the system server 
+    // may also be used.
+    // N.B. The UPS does not require the fingerprint to be a hash. However,
+    // the fingerprint is limited to 32 bytes.    
+    iDigest-&gt;Reset();
+    const TDesC&amp; d = iRequest-&gt;Destination();
+    TPtrC8 p(reinterpret_cast&lt;const TUint8*&gt;(d.Ptr()), d.Length() * 2);
+    TPtrC8 h(iDigest-&gt;Hash(p));
+    
+    CFingerprint* f = CFingerprint::NewLC(h, d);
+    iFingerprints-&gt;AppendL(f);
+    CleanupStack::Pop(f);
+
+    // An empty fingerprint may be used for decisions that apply to
+    // all destinations.
+    f = CFingerprint::NewLC(KNullDesC8, KNullDesC);
+    iFingerprints-&gt;AppendL(f);
+    CleanupStack::Pop(f);
+        
+    User::RequestComplete(iClientStatus, KErrNone);
+    }
+
+void CRefPolicyEvaluator::GenerateFingerprints(
+    const CPromptRequest&amp; aRequest, const CPolicy&amp; aPolicy, 
+    RPointerArray&lt;CFingerprint&gt;&amp; aFingerprints, const CClientEntity*&amp; aClientEntity, 
+    const TAny*&amp; aDialogCreatorParams, TRequestStatus&amp; aStatus)
+    {
+    iRequest = &amp;aRequest;
+    iPolicy = &amp;aPolicy;
+    iFingerprints = &amp;aFingerprints;        
+
+    // This OUT parameter *could* be set to point to data structure
+    // owned by this policy evaluator that is read by the dialog-creator.
+    aDialogCreatorParams = 0;
+    
+    // The client entity field only needs to be set if the policy evaluator
+    // is designed to identify scripts/non-native applications being executed
+    // by the client application.
+    aClientEntity = 0;                
+    
+    iClientStatus = &amp;aStatus;
+    aStatus = KRequestPending;
+    
+    // Kick off policy evaluator state machine
+    iStatus = KRequestPending;
+    TRequestStatus* status = &amp;iStatus;
+    SetActive();
+    User::RequestComplete(status, KErrNone);
+    }
+
+TBool CRefPolicyEvaluator::ForcePromptL(const CDecisionRecord&amp; aDecision, TUint&amp; aNewEvaluatorInfo)
+    {
+    // In this example, if the user selects Never, then they are prompted
+    // once more in-case they did not intend to select Never. 
+    // The "Evaluator Info" field is used to ensure the prompt is only forced once.
+    //
+    // The base class implementation (CPolicyEvaluator::ForcePromptL) 
+    // always returns EFalse.
+    aNewEvaluatorInfo = 1;
+    return (aDecision.iResult == 0 &amp;&amp; aDecision.iEvaluatorInfo == 0);
+    }
+</codeblock> </section>
+</conbody></concept>
\ No newline at end of file