diff -r 4816d766a08a -r f345bda72bc4 Symbian3/PDK/Source/GUID-43080A86-72D3-5422-953E-A5EF79961D7B.dita --- a/Symbian3/PDK/Source/GUID-43080A86-72D3-5422-953E-A5EF79961D7B.dita Tue Mar 30 11:42:04 2010 +0100 +++ b/Symbian3/PDK/Source/GUID-43080A86-72D3-5422-953E-A5EF79961D7B.dita Tue Mar 30 11:56:28 2010 +0100 @@ -1,350 +1,350 @@ - - - - - -Writing -a UPS Policy Evaluator -
Introduction

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.

Note: 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.

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:

    -
  • 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.

  • -
  • Allow a security decision -to be specific to an individual script executing within a scripting host. -This is supported via the client entity field.

  • -
  • 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.

  • -
-
Procedure

Writing policy evaluator includes the -following:

    -
  1. Generating fingerprints

  2. -
  3. Forcing prompts

  4. -
  5. Defining default policy -evaluator

  6. -

Policy evaluators implement the CPolicyEvaluator interface.

Generating -fingerprints

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 destination string, -for example a telephone number, supplied by the service that is matched to -the destination string of a policy in the policy file.

The -policy evaluator must implement the GenerateFingerprints() function, -which is a pure virtual function, declared in the CPolicyEvaluator base -class. The function is asynchronous to allow the implementation to call other -server processes.

The following table describes the parameters for -the GenerateFingerprints() function:

- - - -Parameter -Description - - - - -

aRequest

-

Data that the system server provides to the UPS, including the ClientSid, -ServerSid and ServiceId.

-
- -

aPolicy

-

Details of the policy for the service.

-
- -

aFingerprints

-

Array of fingerprints.

-
- -

aClientEntity

-

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).

-
- -

aDialogCreatorParams

-

Opaque data, which can be any other information for use in the fingerprint -or to be displayed in the dialog.

-
- -

aStatus

-

The request status used to contain completion information for the -function.

-
- - -

The following code fragment is a sample implementation of the GenerateFingerprints() function.

void CRefPolicyEvaluator::GenerateFingerprints( - const CPromptRequest& aRequest, const CPolicy& aPolicy, - RPointerArray<CFingerprint>& aFingerprints, const CClientEntity*& aClientEntity, - const TAny*& aDialogCreatorParams, TRequestStatus& aStatus) - { - iRequest = &aRequest; - iPolicy = &aPolicy; - iFingerprints = &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 = &aStatus; - aStatus = KRequestPending; - - // Kick off policy evaluator state machine - iStatus = KRequestPending; - TRequestStatus* status = &iStatus; - SetActive(); - User::RequestComplete(status, KErrNone); - } -

RunL() is called when the request completes. -The fingerprint is created and appended to the fingerprint array in RunL(). -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.

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->Reset(); - const TDesC& d = iRequest->Destination(); - TPtrC8 p(reinterpret_cast<const TUint8*>(d.Ptr()), d.Length() * 2); - TPtrC8 h(iDigest->Hash(p)); - - CFingerprint* f = CFingerprint::NewLC(h, d); - iFingerprints->AppendL(f); - CleanupStack::Pop(f); - - // An empty fingerprint may be used for decisions that apply to - // all destinations. - f = CFingerprint::NewLC(KNullDesC8, KNullDesC); - iFingerprints->AppendL(f); - CleanupStack::Pop(f); - - User::RequestComplete(iClientStatus, KErrNone); - } -

Forcing prompts

You can implement the ForcePromptL() 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:

    -
  • if a threshold has been -reached, for example the number of MMS messages sent on a particular day

  • -
  • 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

  • -

The UPS invokes the ForcePromptL() function after -a matching record is found in the database. The ForcePromptL() function -is defined in the CPolicyEvaluator base class. The implementation -in the base class always returns EFalse. To force a prompt, -device creators need to override this function and return ETrue. -A sample implementation is as follows. The aNewEvaluatorInfo 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.

TBool CRefPolicyEvaluator::ForcePromptL(const CDecisionRecord& aDecision, TUint& 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 && aDecision.iEvaluatorInfo == 0); - } -

Defining default policy evaluator

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 ForcePromptL() API.

-
Upgrading policy evaluators

A policy evaluator -can be overwritten or eclipsed without restarting the UPS, if it is delivered -through an appropriately signed upgrade.

    -
  • The ECOM plug-in will -be reloaded only when there are no active RUpsSubsession::Authorise() requests.

  • -
  • 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 majorversion number -should be delivered.

  • -
  • SWI Observer informs -the UPS that the plug-ins may have changed whenever Software Install modifies sys\bin on -the system drive. There is no need to explicitly register changes to plug-ins.

  • -
-
Policy evaluator example

The following code shows -an example of a full implementation of the policy evaluator file:

#include "refpolicyevaluator.h" -#include <ecom/implementationproxy.h> -#include <ups/cliententity.h> -#include <ups/fingerprint.h> -#include <ups/upsdb.h> - -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->ConstructL(); - CleanupStack::Pop(self); - return self; - } - -static const TImplementationProxy ImplementationTable[] = - { - IMPLEMENTATION_PROXY_ENTRY(KRefPolicyEvaluatorImplementationId, CRefPolicyEvaluator::CreatePolicyEvaluatorL) - }; - -EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& 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->Reset(); - const TDesC& d = iRequest->Destination(); - TPtrC8 p(reinterpret_cast<const TUint8*>(d.Ptr()), d.Length() * 2); - TPtrC8 h(iDigest->Hash(p)); - - CFingerprint* f = CFingerprint::NewLC(h, d); - iFingerprints->AppendL(f); - CleanupStack::Pop(f); - - // An empty fingerprint may be used for decisions that apply to - // all destinations. - f = CFingerprint::NewLC(KNullDesC8, KNullDesC); - iFingerprints->AppendL(f); - CleanupStack::Pop(f); - - User::RequestComplete(iClientStatus, KErrNone); - } - -void CRefPolicyEvaluator::GenerateFingerprints( - const CPromptRequest& aRequest, const CPolicy& aPolicy, - RPointerArray<CFingerprint>& aFingerprints, const CClientEntity*& aClientEntity, - const TAny*& aDialogCreatorParams, TRequestStatus& aStatus) - { - iRequest = &aRequest; - iPolicy = &aPolicy; - iFingerprints = &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 = &aStatus; - aStatus = KRequestPending; - - // Kick off policy evaluator state machine - iStatus = KRequestPending; - TRequestStatus* status = &iStatus; - SetActive(); - User::RequestComplete(status, KErrNone); - } - -TBool CRefPolicyEvaluator::ForcePromptL(const CDecisionRecord& aDecision, TUint& 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 && aDecision.iEvaluatorInfo == 0); - } -
+ + + + + +Writing +a UPS Policy Evaluator +
Introduction

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.

Note: 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.

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:

    +
  • 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.

  • +
  • Allow a security decision +to be specific to an individual script executing within a scripting host. +This is supported via the client entity field.

  • +
  • 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.

  • +
+
Procedure

Writing policy evaluator includes the +following:

    +
  1. Generating fingerprints

  2. +
  3. Forcing prompts

  4. +
  5. Defining default policy +evaluator

  6. +

Policy evaluators implement the CPolicyEvaluator interface.

Generating +fingerprints

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 destination string, +for example a telephone number, supplied by the service that is matched to +the destination string of a policy in the policy file.

The +policy evaluator must implement the GenerateFingerprints() function, +which is a pure virtual function, declared in the CPolicyEvaluator base +class. The function is asynchronous to allow the implementation to call other +server processes.

The following table describes the parameters for +the GenerateFingerprints() function:

+ + + +Parameter +Description + + + + +

aRequest

+

Data that the system server provides to the UPS, including the ClientSid, +ServerSid and ServiceId.

+
+ +

aPolicy

+

Details of the policy for the service.

+
+ +

aFingerprints

+

Array of fingerprints.

+
+ +

aClientEntity

+

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).

+
+ +

aDialogCreatorParams

+

Opaque data, which can be any other information for use in the fingerprint +or to be displayed in the dialog.

+
+ +

aStatus

+

The request status used to contain completion information for the +function.

+
+ + +

The following code fragment is a sample implementation of the GenerateFingerprints() function.

void CRefPolicyEvaluator::GenerateFingerprints( + const CPromptRequest& aRequest, const CPolicy& aPolicy, + RPointerArray<CFingerprint>& aFingerprints, const CClientEntity*& aClientEntity, + const TAny*& aDialogCreatorParams, TRequestStatus& aStatus) + { + iRequest = &aRequest; + iPolicy = &aPolicy; + iFingerprints = &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 = &aStatus; + aStatus = KRequestPending; + + // Kick off policy evaluator state machine + iStatus = KRequestPending; + TRequestStatus* status = &iStatus; + SetActive(); + User::RequestComplete(status, KErrNone); + } +

RunL() is called when the request completes. +The fingerprint is created and appended to the fingerprint array in RunL(). +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.

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->Reset(); + const TDesC& d = iRequest->Destination(); + TPtrC8 p(reinterpret_cast<const TUint8*>(d.Ptr()), d.Length() * 2); + TPtrC8 h(iDigest->Hash(p)); + + CFingerprint* f = CFingerprint::NewLC(h, d); + iFingerprints->AppendL(f); + CleanupStack::Pop(f); + + // An empty fingerprint may be used for decisions that apply to + // all destinations. + f = CFingerprint::NewLC(KNullDesC8, KNullDesC); + iFingerprints->AppendL(f); + CleanupStack::Pop(f); + + User::RequestComplete(iClientStatus, KErrNone); + } +

Forcing prompts

You can implement the ForcePromptL() 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:

    +
  • if a threshold has been +reached, for example the number of MMS messages sent on a particular day

  • +
  • 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

  • +

The UPS invokes the ForcePromptL() function after +a matching record is found in the database. The ForcePromptL() function +is defined in the CPolicyEvaluator base class. The implementation +in the base class always returns EFalse. To force a prompt, +device creators need to override this function and return ETrue. +A sample implementation is as follows. The aNewEvaluatorInfo 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.

TBool CRefPolicyEvaluator::ForcePromptL(const CDecisionRecord& aDecision, TUint& 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 && aDecision.iEvaluatorInfo == 0); + } +

Defining default policy evaluator

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 ForcePromptL() API.

+
Upgrading policy evaluators

A policy evaluator +can be overwritten or eclipsed without restarting the UPS, if it is delivered +through an appropriately signed upgrade.

    +
  • The ECOM plug-in will +be reloaded only when there are no active RUpsSubsession::Authorise() requests.

  • +
  • 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 majorversion number +should be delivered.

  • +
  • SWI Observer informs +the UPS that the plug-ins may have changed whenever Software Install modifies sys\bin on +the system drive. There is no need to explicitly register changes to plug-ins.

  • +
+
Policy evaluator example

The following code shows +an example of a full implementation of the policy evaluator file:

#include "refpolicyevaluator.h" +#include <ecom/implementationproxy.h> +#include <ups/cliententity.h> +#include <ups/fingerprint.h> +#include <ups/upsdb.h> + +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->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +static const TImplementationProxy ImplementationTable[] = + { + IMPLEMENTATION_PROXY_ENTRY(KRefPolicyEvaluatorImplementationId, CRefPolicyEvaluator::CreatePolicyEvaluatorL) + }; + +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& 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->Reset(); + const TDesC& d = iRequest->Destination(); + TPtrC8 p(reinterpret_cast<const TUint8*>(d.Ptr()), d.Length() * 2); + TPtrC8 h(iDigest->Hash(p)); + + CFingerprint* f = CFingerprint::NewLC(h, d); + iFingerprints->AppendL(f); + CleanupStack::Pop(f); + + // An empty fingerprint may be used for decisions that apply to + // all destinations. + f = CFingerprint::NewLC(KNullDesC8, KNullDesC); + iFingerprints->AppendL(f); + CleanupStack::Pop(f); + + User::RequestComplete(iClientStatus, KErrNone); + } + +void CRefPolicyEvaluator::GenerateFingerprints( + const CPromptRequest& aRequest, const CPolicy& aPolicy, + RPointerArray<CFingerprint>& aFingerprints, const CClientEntity*& aClientEntity, + const TAny*& aDialogCreatorParams, TRequestStatus& aStatus) + { + iRequest = &aRequest; + iPolicy = &aPolicy; + iFingerprints = &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 = &aStatus; + aStatus = KRequestPending; + + // Kick off policy evaluator state machine + iStatus = KRequestPending; + TRequestStatus* status = &iStatus; + SetActive(); + User::RequestComplete(status, KErrNone); + } + +TBool CRefPolicyEvaluator::ForcePromptL(const CDecisionRecord& aDecision, TUint& 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 && aDecision.iEvaluatorInfo == 0); + } +
\ No newline at end of file