|
||
class CPolicyServer : public CServer2;
A security policy framework built on top of the normal CServer2
class.
The two major functions of the Policy Server framework are to check a received message against a security policy and then
to perform an action depending on the result of this check. The exact behaviour is defined by the contents of the CPolicyServer::TPolicy
structure given in the constructor for CPolicyServer.
The processing performed when a server receives a message are describe below. This should aid understanding of the interaction
of the CPolicyServer::TPolicy
structure and virtual member functions which may be implemented by classes derived from CPolicyServer.
Checking the Security Policy
On receipt of a message, the message function number is used to search the list of ranges pointed to by CPolicyServer::TPolicy::iRanges
. This yields a range number R, which is between 0 and CPolicyServer::TPolicy::iRangeCount
-1. The policy index, X, for this range is then fetched from CPolicyServer::TPolicy::iElementsIndex
[R]. If the message is a Connect message, then X is fetched directly from CPolicyServer::TPolicy::iOnConnect
instead.
The further action taken is determined by the value of X.
If X==TSpecialCase::EAlwaysPass, the message is processed as normal; either by passing it to the ServiceL() method of a session, or, in the case of a connection message, a new session is created.
If X==TSpecialCase::ENotSupported, the message is completed with KErrNotSupported.
If X==TSpecialCase::ECustomCheck, a call to the virtual function CPolicyServer::CustomSecurityCheckL(const RMessage2 &,TInt &,TSecurityInfo &)
is made. The implementation of this method must return one of the TCustomResult enumerations which determine what further
action is to be taken:
TCustomResult::EPass The message is processed as normal; either by passing it to the ServiceL() method of a session, or, in the case of a connection message, a new session is created.
TCustomResult::EFail This causes CPolicyServer::CheckFailedL(const RMessage2 &,TInt,const TSecurityInfo &)
to be called with the action specified by the aAction reference given to CPolicyServer::CustomSecurityCheckL(const RMessage2 &,TInt &,TSecurityInfo &)
(This defaults to TFailureAction::EFailClient.)
TCustomResult::EAsync The derived class is responsible for further processing of the message, the Policy Server framework will do nothing more with it.
If X < TSpecialCase::ESpecialCaseHardLimit, X is taken as an index into the array of CPolicyServer::TPolicyElement
objects pointed to by CPolicyServer::TPolicy::iElements
. The platform security attributes of the process which sent the message being processed are checked against the security
policy specified in this CPolicyServer::TPolicyElement
. If the process possesses all of the attributes specified then the message processed as normal. Otherwise, CPolicyServer::CheckFailedL(const RMessage2 &,TInt,const TSecurityInfo &)
is called with the action value specified in the CPolicyServer::TPolicyElement
.
Handling Policy Check Failure
The CPolicyServer::CheckFailedL(const RMessage2 &,TInt,const TSecurityInfo &)
method is called when a security check has failed. It performs an action according to the aAction value given to it:
If aAction==TFailureAction::EFailClient, the message is completed with KErrPermissionDenied.
If aAction==TFailureAction::EPanicClient, the client thread is panicked.
If aAction < 0 a call to the virtual function CPolicyServer::CustomFailureActionL(const RMessage2 &,TInt,const TSecurityInfo &)
is made. The implementation of this method must return one of the TCustomResult enumerations which determine what further
action is to be taken:
TCustomResult::EPass The message is processed as normal; either by passing it to the ServiceL() method of a session, or, in the case of a connection message, a new session is created.
TCustomResult::EFail The message is completed with KErrPermissionDenied.
TCustomResult::EAsync The derived class is responsible for further processing of the message, the Policy Server framework will do nothing more with it.
CBase
-
Base class for all classes to be instantiated on the heap.
CActive
-
The core class of the active object abstraction.
CServer2
-
Abstract base class for servers (version 2).
CPolicyServer
- A security policy framework built on top of the normal CServer2 class.
Defined in CPolicyServer
:
CPolicyServer(TInt,const TPolicy &,TServerType)
Construct a policy serverCheckFailedL(const RMessage2 &,TInt,const TSecurityInfo &)
Called when a security check has failed.CustomFailureActionL(const RMessage2 &,TInt,const TSecurityInfo &)
Performs a custom action after the failure of a security check. Derived server c...CustomSecurityCheckL(const RMessage2 &,TInt &,TSecurityInfo &)
Performs a custom security check. Derived server classes must implement this fun...EAlwaysPass
Indicates that the message is requesting an unrestricted function and therefore ...EAsync
Security checking will be performed asynchronously. ECustomCheck
Indicates a custom check should be made by calling CPolicyServer::CustomSecurity...EFail
Security check failed. EFailClient
Complete message with KErrPermissionDenied ENotSupported
Indicates that message is requesting an unsupported function. The message is com...EPanicClient
Panic client EPass
Security check passed. Extension_(TUint,TAny *&,TAny *)
Extension function ProcessError(const RMessage2 &,TInt)
Called if a leave occurs during processing of a message. The underlying framewor...ProcessL(const RMessage2 &)
Process an accepted message which has passed its policy check.RunError(TInt)
Handles the situation where a call to CServer2::RunL(), leaves.RunL()
Handles the receipt of a message. TCustomResult
Enumeration of acceptable return codes from both of CPolicyServer::CustomSecurit...TFailureAction
Enumeration specifying action to take if a security check fails. Values >= 0 ...TPolicy
Object specifying which security checks to perform on each request number and wh...TPolicyElement
Class specifying a security check and the action to takeTSpecialCase
Special case values which can be used instead of a policy element index containe...Inherited from CActive
:
CActive(TInt)
Constructs the active object with the specified priority.Cancel()
Cancels the wait for completion of an outstanding request.Deque()
Removes the active object from the active scheduler's list of active objects.EPriorityHigh
A priority higher than EPriorityUserInput.EPriorityIdle
A low priority, useful for active objects representing background processing.EPriorityLow
A priority higher than EPriorityIdle but lower than EPriorityStandard.EPriorityStandard
Most active objects will have this priority.EPriorityUserInput
A priority higher than EPriorityStandard; useful for active objects handling use...IsActive()const
Determines whether the active object has a request outstanding.IsAdded()const
Determines whether the active object has been added to the active scheduler's li...Priority()const
Gets the priority of the active object.SetActive()
Indicates that the active object has issued a request and that it is now outstan...SetPriority(TInt)
Sets the priority of the active object.TPriority
Defines standard priorities for active objects. iStatus
The request status associated with an asynchronous request.Inherited from CBase
:
Delete(CBase *)
Deletes the specified object.operator new(TUint)
Allocates the object from the heap and then initialises its contents to binary z...operator new(TUint,TAny *)
Initialises the object to binary zeroes.operator new(TUint,TLeave)
Allocates the object from the heap and then initialises its contents to binary z...operator new(TUint,TLeave,TUint)
Allocates the object from the heap and then initialises its contents to binary z...operator new(TUint,TUint)
Allocates the object from the heap and then initialises its contents to binary z...Inherited from CServer2
:
CServer2(TInt,TServerType)
Constructs the server object, specifying the server type and the active object p...DoCancel()
Implements the cancellation of any outstanding request for messages. DoConnect(const RMessage2 &)
Handles the connect request from the client.EGlobalSharableSessions
The session is sharable with all other threads in the system.ESharableSessions
The session is sharable with other threads in the same process.EUnsharableSessions
The session is not sharable with other threads.Message()const
Gets a reference to the server's current message.ReStart()
Restarts the server.Server()const
Gets a handle to the server.Start(const TDesC &)
Adds the server with the specified name to the active scheduler, and issues the ...StartL(const TDesC &)
Adds the server with the specified name to the active scheduler, and issues the ...TServerType
Defines the set of session types that the server can create.iSessionIter
protected: IMPORT_C CPolicyServer(TInt aPriority, const TPolicy &aPolicy, TServerType aType=EUnsharableSessions);
Construct a policy server
|
IMPORT_C void ProcessL(const RMessage2 &aMsg);
Process an accepted message which has passed its policy check.
The message is either passed to the ServiceL() method of a session, or, in the case of a connection message, a new session is created.
This is called by CPolicyServer::RunL()
to process a message which has passed its security check. If the server implementation returns EAsync from either CPolicyServer::CustomSecurityCheckL(const RMessage2 &,TInt &,TSecurityInfo &)
or CPolicyServer::CustomFailureActionL(const RMessage2 &,TInt,const TSecurityInfo &)
, then it is the responsibility of the derived server implementation to call ProcessL at a later point if the messages passes
the asynchronous check.
This function should only ever be called by derived implementations if asynchronous security checks are in use.
|
IMPORT_C void CheckFailedL(const RMessage2 &aMsg, TInt aAction, const TSecurityInfo &aMissing);
Called when a security check has failed.
The aAction parameter determines the action taken:
If aAction==TFailureAction::EFailClient, the message is completed with KErrPermissionDenied.
If aAction==TFailureAction::EPanicClient, the client thread is panicked.
If aAction < 0 a call to the virtual function CPolicyServer::CustomFailureActionL(const RMessage2 &,TInt,const TSecurityInfo &)
is made.
This function should only ever be called by derived implementations if asynchronous security checks are in use.
|
IMPORT_C void ProcessError(const RMessage2 &aMsg, TInt aError);
Called if a leave occurs during processing of a message. The underlying framework ensures that leaves which occur during CSession2::ServiceL(const RMessage2 &)
are passed to CSession2::ServiceError(const RMessage2 &,TInt)
. Leaves occuring prior to this (ie. during CPolicyServer::CustomSecurityCheckL(const RMessage2 &,TInt &,TSecurityInfo &)
or CPolicyServer::CustomFailureActionL(const RMessage2 &,TInt,const TSecurityInfo &)
) are completed with the leave code.
This function should only ever be called by derived implementations if asynchronous security checks are in use. In this case
the CPolicyServer::RunError(TInt)
of that other active object must call CPolicyServer::ProcessError(const RMessage2 &,TInt)
.
|
protected: IMPORT_C virtual TCustomResult CustomSecurityCheckL(const RMessage2 &aMsg, TInt &aAction, TSecurityInfo &aMissing);
Performs a custom security check. Derived server classes must implement this function if any element in iElementsIndex has
the value CPolicyServer::ECustomCheck
. Similarly, if CPolicyServer::ECustomCheck
is not used, then this function can be safely ignored.
If CPolicyServer::ECustomCheck
is used, there are two further cases to consider:
The custom security check can synchronously decide if the message should pass. In this case, the derived implementation must simply return either EPass or EFail depending on the result of the security check.
The custom security check needs to use asynchronous methods in order to determine whether the message should procceed. In this case, these asysnchronous methods should be started and then the EAsync value returned. Furthermore, implmentations returning EAsync commit to the following:
If the security check eventually passes, CPolicyServer::ProcessL(const RMessage2 &)
must be called with the appropriate message.
If the security check eventually fails, CPolicyServer::CheckFailedL(const RMessage2 &,TInt,const TSecurityInfo &)
must be called with that message.
Pending messages on a given session need to be completed and discarded if the session is closed.
IMPORTANT NOTE. When processing a message asynchronously, a copy must be made of the RMessage2
object. Saving a refernece or pointer to the original message will produce unpredictable defects. This is because the object
will be reused for the next message that the server receives.
In both cases, synchronous and asynchronous, the derived implementation has the option of updating the aAction and/or aMissing parameters if that is appropriate.
|
|
|
protected: IMPORT_C virtual TCustomResult CustomFailureActionL(const RMessage2 &aMsg, TInt aAction, const TSecurityInfo &aMissing);
Performs a custom action after the failure of a security check. Derived server classes must implement this function if the
aAction value passed to CPolicyServer::CheckFailedL(const RMessage2 &,TInt,const TSecurityInfo &)
is less than zero. This can happened if the policy specified a negative number in the iAction member of any of the TPolicyElements,
or, if the derived CPolicyServer::CustomSecurityCheckL(const RMessage2 &,TInt &,TSecurityInfo &)
modified the value of aAction prior to returning.
If negative aAction values are used, there are two further cases to consider:
The custom security check can synchronously decide if the message should pass. In this case, the derived implementation must simply return either EPass or EFail depending on the result of the security check.
The custom security check needs to use asynchronous methods in order to determine whether the message should still proceed. In this case, these asysnchronous methods should be started and then the EAsync value returned. Furthermore, implmentations returning EAsync commit to the following:
If the security check eventually passes, CPolicyServer::ProcessL(const RMessage2 &)
must be called with the appropriate message.
If the security check eventually fails, or if a fatal error condition occurs, including if the previously mentioned call to
CPolicyServer::ProcessL(const RMessage2 &)
leaves; then CPolicyServer::ProcessError(const RMessage2 &,TInt)
should be called passing the message and relevant error code.
Pending messages on a given session need to be completed and discarded if the session is closed.
IMPORTANT NOTE. When processing a message asynchronously, a copy must be made of the RMessage2
object. Saving a refernece or pointer to the original message will produce unpredictable defects. This is because the object
will be reused for the next message that the server receives.
The default implementation of this function panics the server.
|
|
|
protected: IMPORT_C virtual TInt Extension_(TUint aExtensionId, TAny *&a0, TAny *a1);
Extension function
|
|
private: IMPORT_C virtual TInt RunError(TInt aError);
Handles the situation where a call to CServer2::RunL()
, leaves.
This is the server active object's implementation of the active object framework's CPolicyServer::RunError(TInt)
function.
In practice, the leave can only be caused by a session's ServiceL() function, which is called from this CPolicyServer::RunL()
; this error is reflected back to that session by calling its ServiceError() function.
|
|
CActive::RunL()
Handles an active object's request completion event.CActive::RunError(TInt)
Handles a leave occurring in the request completion event handler CActive::RunL(...CSession2::ServiceError(const RMessage2 &,TInt)
Handles the situation when a call to CSession2::ServiceL(const RMessage2 &),...class TPolicyElement;
Class specifying a security check and the action to take
If iAction is >=0 it must be a member of TFailureAction If iAction is <0 it is assumed to specify a custom action specific to the derived implementation. In this case, CustomFailureActionL must be implemented by the derived class.
Defined in CPolicyServer::TPolicyElement
:
iAction
Action to take on failure. Either a value from TFailureAction or a negative valu...iPolicy
Security policy to check against the client which sent a message.iPolicy
TStaticSecurityPolicy iPolicy;
Security policy to check against the client which sent a message.
This class can specify a security policy consisting of either:
A check for between 0 and 7 capabilities
A check for a given Secure ID along with 0-3 capabilities
A check for a given Vendor ID along with 0-3 capabilities
This member should only be initialised by one of the following macros:
_INIT_SECURITY_POLICY_PASS
_INIT_SECURITY_POLICY_FAIL
_INIT_SECURITY_POLICY_C1
_INIT_SECURITY_POLICY_C2
_INIT_SECURITY_POLICY_C3
_INIT_SECURITY_POLICY_C4
_INIT_SECURITY_POLICY_C5
_INIT_SECURITY_POLICY_C6
_INIT_SECURITY_POLICY_C7
_INIT_SECURITY_POLICY_S0
_INIT_SECURITY_POLICY_S1
_INIT_SECURITY_POLICY_S2
_INIT_SECURITY_POLICY_S3
_INIT_SECURITY_POLICY_V0
_INIT_SECURITY_POLICY_V1
_INIT_SECURITY_POLICY_V2
_INIT_SECURITY_POLICY_V3
CPolicyServer::TPolicy
Object specifying which security checks to perform on each request number and wh...iAction
TInt iAction;
Action to take on failure. Either a value from TFailureAction or a negative value which has meaning to the CPolicyServer::CustomFailureActionL(const RMessage2 &,TInt,const TSecurityInfo &)
method of a derived class.
class TPolicy;
Object specifying which security checks to perform on each request number and what action to take if the check fails.
Explanations of each of the members of this class are detailed below.
As explained in CPolicyServer::CPolicyServer(TInt,const TPolicy &,TServerType)
, it is important that the instance of this class (CPolicyServer::TPolicy) given to the policy server constructor, exists
for the lifetime of the server. For this reason, as well as code size considerations, it is recommended that the CPolicyServer::TPolicy
instance is const static data. The following code segment shows the recommended way of doing this. Further detail on what
each of these statements means is given below.
const TUint myRangeCount = 4;
const TInt myRanges[myRangeCount] =
{
0, //range is 0-2 inclusive
3, //range is 3-6 inclusive
7, //range is 7
8, //range is 8-KMaxTInt inclusive
};
const TUint8 myElementsIndex[myRangeCount] =
{
1, //applies to 0th range (req num: 0-2)
CPolicyServer::ECustomCheck, //applies to 1st range (req num: 3-6)
0, //applies to 2nd range (req num: 7)
CPolicyServer::ENotSupported, //applies to 3rd range (req num: 8-KMaxTInt)
};
const CPolicyServer::TPolicyElement myElements[] =
{
{_INIT_SECURITY_POLICY_C1(ECapabilityDiskAdmin), CPolicyServer::EFailClient},
{_INIT_SECURITY_POLICY_C1(ECapabilityLocation), CMyPolicyServer::EQueryUser},
}
const CPolicySErver::TPolicy myPolicy =
{
CPolicyServer::EAlwaysPass, //specifies all connect attempts should pass
myRangeCount,
myRanges,
myElementsIndex,
myElements,
}
Defined in CPolicyServer::TPolicy
:
iElements
A pointer to an array of distinct policy elements.iElementsIndex
A pointer to an array of TUint8 values specifying the appropriate action to take...iOnConnect
The index into iElements, or an allowed value of TSpecialCase, that is used to c...iRangeCount
Number of ranges in the iRanges array. iRanges
A pointer to an array of ordered ranges of request numbers. Each element in this...iOnConnect
TUint8 iOnConnect;
The index into iElements, or an allowed value of TSpecialCase, that is used to check a connection attempt .
iRangeCount
TUint16 iRangeCount;
Number of ranges in the iRanges array.
iRanges
const TInt * iRanges;
A pointer to an array of ordered ranges of request numbers. Each element in this array refers to the starting request number of a range. The range of the previous element is up to and including the current element minus 1. Thus an array like:
const TInt myRanges[4] = {0, 3, 7, 8};
means that:
the 0th range is 0-2 (inclusive).
the 1st range is 3-6 (inclusive).
the 2nd range is solely request number 7.
the 3rd range is 8-KMaxTInt (inclusive).
Note that the all possible request numbers must be accounted for. This implies that the first element must be 0. It also implies that the last range goes from the that element to KMaxTint. Finally, each element must be strictly greater than the previous element. As the first element is 0, this clearly implies that iRanges must not contain negative elements.
iElementsIndex
const TUint8 * iElementsIndex;
A pointer to an array of TUint8 values specifying the appropriate action to take for each range in iRanges. For example, the 0th element of iElementsIndex specifies the appropriate action to take for the 0th range in iRanges. As such, iElementsIndex must have precisely the same number of elements as iRanges.
The following rules apply to the value of each element in iElementsIndex:
Each value must be a valid index into iElements (that is, less than the number of elements in iElements) OR a valid value from TSpecialCase.
Elements' values need not follow any special ordering.
Elements may repeat values.
Continuing the example from iRanges:
const TInt myRanges[4] = {0, 3, 7, 8};
const TUInt8 myElementsIndex[4] = {
1,
CPolicyServer::ECustomCheck,
0,
CPolicyServer::ENotSupported
};
This means that:
Requests within the first range of myRanges (request numbers 0-2) will be checked against the policy specified by the 1st element of iElements.
Requests with the the second range of myRanges (request numbers 3-6) require a custom check to determine if they are allowed.
This requires derived server implementations to implement CPolicyServer::CustomSecurityCheckL(const RMessage2 &,TInt &,TSecurityInfo &)
Requests within the third range of myRanges (request number 7) will be checked against the policy specified by the 0th element of iElements.
Requests within the fourth range of myRanges (request numbers 8-KMaxTInt) will automatically be completed with KErrNotSupported by the policy server framework.
iElements
const TPolicyElement * iElements;
A pointer to an array of distinct policy elements.
Continuing with the previous examples:
const TInt myRanges[4] = {0, 3, 7, 8};
const TUInt8 myElementsIndex[4] = {
1,
CPolicyServer::ECustomCheck,
0,
CPolicyServer::ENotSupported
};
const TPolicyElement iElements[] = {
{_INIT_SECURITY_POLICY_C1(ECapabilityDiskAdmin), CPolicyServer::EFailClient},
{_INIT_SECURITY_POLICY_C1(ECapabilityLocation), CMyPolicyServer::EQueryUser}
}
The instantiation of iElements specifies that:
Request numbers 0-2 require the Location capability. As the iAction member of the 1st element specifies a custom action (represented by the negative number, CMyPolicyServer::EQueryUser), requests without Location will passed to the reimplementation of CustomFailureActionL.
Request number 7 requires the DiskAdmin capability. Requestors without DiskAdmin will have their request completed with KErrPermissionDenied.
TFailureAction
Enumeration specifying action to take if a security check fails. Values >= 0 are handled by CPolicyServer::CheckFailedL(const RMessage2 &,TInt,const TSecurityInfo &)
. Values < 0 are specific to the derived implementation of the policy server and will result in a call to CPolicyServer::CustomFailureActionL(const RMessage2 &,TInt,const TSecurityInfo &)
if a security check fails. Attempts to use undefined values >= 0 will result in a panic in CPolicyServer::CheckFailedL(const RMessage2 &,TInt,const TSecurityInfo &)
.
|
TCustomResult
Enumeration of acceptable return codes from both of CPolicyServer::CustomSecurityCheckL(const RMessage2 &,TInt &,TSecurityInfo &)
and CPolicyServer::CustomFailureActionL(const RMessage2 &,TInt,const TSecurityInfo &)
. Results of EPass or EFail are handled by the CPolicyServer framework. No other action is required on the part of the derived
implementation. However, results of EAsync imply that the derived implementation will call the appropriate function once the
result is known. See CPolicyServer::CustomSecurityCheckL(const RMessage2 &,TInt &,TSecurityInfo &)
and CustomFailureActionL for more information.
|
TSpecialCase
Special case values which can be used instead of a policy element index contained in the array CPolicyServer::TPolicy::iElementsIndex
|