programming4us
programming4us
MOBILE

Mobile Application Security : SymbianOS Security - Interprocess Communication

- How To Install Windows Server 2012 On VirtualBox
- How To Bypass Torrent Connection Blocking By Your ISP
- How To Install Actual Facebook App On Kindle Fire
2/23/2011 9:22:10 AM
SymbianOS supports kernel-mediated communication between running processes. Thanks to the protected memory model, a process cannot directly modify the memory space of another running process. Interprocess communication is still a desirable activity—for example, dividing a single executable into two executables that communicate to provide a separation of concerns.

Client/Server Sessions

A client/server IPC model is used pervasively throughout SymbianOS. A number of the OS-provided services are implemented in two components: a server process and a client DLL that creates a session with the server. The server is an independent, long-running process with its own SecureID. The client DLL is loaded by client processes and maintains a mapping between function names and ordinal function numbers. Note that the client DLL is not strictly necessary, but the developer must interact with the server in the same fashion.

Part of implementing a client/server interface includes the ability to enforce a particular security policy as to which clients can connect to a server and which servers a client will connect to. A security policy is defined using one of fifteen _LIT_SECURITY_POLICY macros. These macros can be grouped in three categories: Capability enforcement, SecureID enforcement, and VendorID enforcement. A listing of these macros can be seen in Table 1. A server can and should validate the capabilities of clients that connect to it in order to prevent capability leakage where a privileged server performs sensitive actions on behalf of an unprivileged client. A server can also enforce that only clients with a particular SecureID can connect to it. This can be useful when implementing an application model where sensitive actions are performed in a small second process. Finally, a server can enforce that only clients from a particular vendor can connect to it when the vendor factors out sensitive actions into a common process that each of its applications should be able to access.

Table 1. Security Policy Macros
MacroPurpose
_LIT_SECURITY_POLICY_C1Enforce one capability
_LIT_SECURITY_POLICY_C2Enforce two capabilities
_LIT_SECURITY_POLICY_C3Enforce three capabilities
_LIT_SECURITY_POLICY_C4Enforce four capabilities
_LIT_SECURITY_POLICY_C5Enforce five capabilities
_LIT_SECURITY_POLICY_C6Enforce six capabilities
_LIT_SECURITY_POLICY_C7Enforce seven capabilities
_LIT_SECURITY_POLICY_S0Enforce a SecureID
_LIT_SECURITY_POLICY_S1Enforce a SecureID and one capability
_LIT_SECURITY_POLICY_S2Enforce a SecureID and two capabilities
_LIT_SECURITY_POLICY_S3Enforce a SecureID and three capabilities
_LIT_SECURITY_POLICY_V0Enforce a VendorID
_LIT_SECURITY_POLICY_V1Enforce a VendorID and one capability
_LIT_SECURITY_POLICY_V2Enforce a VendorID and two capabilities
_LIT_SECURITY_POLICY_V3Enforce a VendorID and three capabilities

Each of these macros is used in the same general way. The first parameter specifies the name of a new policy object. For SecureID macros, the second parameter specifies the targeted SecureID. For VendorID macros, the second parameter specifies the targeted VendorID. The rest of the parameters are one of the enumerated capabilities, the number of which is specified in the macro name.

_LIT_SECURITY_POLICY_S0(KCustomServerSID, 0xE0000001);
_LIT_SECURITY_POLICY_V1(KClientVIDOneCap, 0xE0000001, ECapabilityDiskAdmin);
_LIT_SECURITY_POLICY_C2(KEnforceTwoCaps, ECapabilityReadUserData,
ECapabilityWriteUserData);


Client sessions are created via an RSessionBase object and a call to the CreateSession() method. Most client DLLs will derive their own subclass that calls this method with the appropriate parameters. During the 9.x series, another overload of CreateSession() was added that takes a pointer to a TSecurityPolicy object. This allows a client to validate the SecureID or VendorID of the named server. Messages to the server are delivered and responses obtained through the SendReceive() method. Most client DLLs will provide wrapper functions for calls to SendReceive() to provide a more natural interface. The code below shows the basic pattern behind writing a client proxy object. This class will reside within a client DLL and hide the interprocess communication details.

_LIT(KCustomServerName, "com_isecpartners_custom");

enum TCustomServerMessages {
EDoStuff
};

class RCustomSession : public RSessionBase {
public:
IMPORT_C TInt Connect();
IMPORT_C TInt DoStuff(const LString& str);
};

EXPORT_C TInt RCustomSession::Connect() {
return CreateSession(KCustomServerName,
TVersion(),
KServerDefaultMessageSlots,
EIpcSession_Unsharable,
&KCustomServerSID());
}

EXPORT_C TInt RCustomSession::DoStuff(const LString& str) {
return SendReceive(EDoStuff, TIpcArgs(&str));
}

Servers are created by deriving two of three classes: CSession2 and either CServer2 or CPolicyServer. CServer2 works well in many cases—namely, where the security policy to be enforced is straightforward (for example, restricting potential clients to those with a particular SecureID upon session connection or requiring a particular capability to call a certain method). In order to enforce a policy with a CSession2 or CServer2 class, call the CheckPolicy() method of a SecurityPolicy object with RMessage& as the first parameter. The result of this method is a boolean indicating whether the message was delivered by a process that conforms to the policy. Wrapping calls to this method in an if statement allows for corrective action to be taken. In the following example, the corrective action is to “leave” with a permission-denied error:

class CCustomSession : public CSession2 {
private:
void ServiceL(const RMessage2& msg);
TInt doStuff(const LString& str);
TInt getStuff (LString& str);
};

void CCustomSession::ServiceL(const RMessage2& msg) {
TInt status = KErrNotSupported;
switch (aMessage.Function()) {
case EDoStuff: {
LString param(msg.GetDesLengthL(0));
msg.ReadL(0, param);
status = doStuff(param);
break;
}
case EGetStuff :{
if(!KEnforceTwoCaps().CheckPolicy (msg,
__PLATSEC_DIAGNOSTIC_STRING("CCustomSession::ServiceL"))) {
User::Leave(KErrPermissionDenied);
}

LString result;
status = getStuff(result);

__ASSERT_ALWAYS(result.Length() <= msg.GetDesMaxLengthL(0),
User::Leave(KErrBadDescriptor));
msg.WriteL(0, result);
break;
}
default: {
_LIT(KErrMsg, "Unknown function call!");
msg.Panic(KErrMsg, KErrNotSupported);
}
}
aMessage.Complete(status);
}


class CCustomServer : public CServer2 {
public:
CCustomServer(TInt priority = EPriorityNormal);

private:
CSession2* NewSessionL(const TVersion& version,
const RMessage2& msg) const;
};

CCustomServer::CCustomServer(TInt priority) : CServer2(priority,
ESharableSessions) {
Start(KCustomServerName);
}
CSession2* CCustomServer::NewSessionL(const TVersion&,
const RMessage2&) const {
if(!KClientVIDOneCap().CheckPolicy(msg,
__PLATSEC_DIAGNOSTIC_STRING("CCustomServer::NewSessionL"))) {
User::Leave(KErrPermissionDenied);
}
return new (ELeave) CCustomSession();
}


CPolicyServer should be chosen when the policy to be enforced is very complex. Although substantially more complex in simple cases, it can be much simpler in complex cases. The framework automatically handles checking a prospective client’s policy conformance upon session initiation and for each message. The first step is to create an array of message numbers in sorted increasing order. Each number need not be represented, just the lower bound of a range that shares the same policy. That is, if functions 0 through 3 share a policy and function 4 has its own policy, then the array should have two elements: 0 and 4. Next, a second array is created that must be the same size as the previous one to contain indices into a third array. This third array contains the separate policy-enforcement objects. When a message is sent to the server, its function number (or the closest number less than it) is found in the first array and the index is noted. This index is used to reference into the second array in order to obtain the index into the third array, where the actual policy object is found. Conceptually this can be imagined as a dictionary that maps a function ordinal to the policy to be applied, where the first array holds the dictionary key and the second array holds a reference to the policy. The code below demonstrates the basics behind using the CPolicyServer class to reduce the developer effort required to enforce complex security policies.

const TUInt rangesCount = 3;

const TInt msgNumRanges[rangesCount] = {
0, // EDoStuff
1, // EGetStuff
2 // Non-existent functions
};

const TUInt8 msgPolicyIndices[] = {
CPolicyServer::EAlwaysPass, // EDoStuff
1, // EGetStuff
CPolicyServer::EBadMessageNumber // Non-existent functions
};

const CPolicyServer::TPolicyElement msgPolicies[] = {
{
_INIT_SECURITY_POLICY_V1(0xE0000001, ECapabilityDiskAdmin),
CPolicyServer::EFailClient
},
{
_INIT_SECURITY_POLICY_C2(ECapabilityReadUserData,
ECapabilityWriteUserData),
CPolicyServer::EFailClient
}
};

const CPolicyServer::TPolicy customPolicy = {
0,
rangesCount,
msgNumberRanges,
msgPolicyIndices,
msgPolicies
};

class CCustomPolicyServer : public CPolicyServer {
public:
CCustomPolicyServer(TInt priority = EPriorityNormal);

private:
CSession2* NewSessionL(const TVersion& version,
const RMessage2& msg) const;
};

CCustomPolicyServer::CCustomServer(TInt priority) :
CPolicyServer(priority, CustomPolicy, ESharableSessions) {
Start(KCustomServerName);
}

CSession2* CCustomPolicyServer::NewSessionL(const TVersion&,
const RMessage2&) const {
return new (ELeave) CCustomSession();
}


Shared Sessions

Sessions can be created as unsharable, sharable between threads within the same process, or sharable between processes. This is defined on both the client and server sides. When CreateSession() is called on the client, one of the parameters specifies the desired session sharing. The CServer2() constructor specifies the type of sessions that can be created.

Use caution when allowing globally sharable sessions and implementing a policy where clients are checked at session initialization. A client that does not meet the policy could obtain a session handle from a process that did. This is especially true when implementing subsessions. Subsessions maintain a reference to the parent session (which maintains a list of open subsessions). When sharing a subsession, be aware that all of the other active subsessions are also exposed.

Shared Handles

Another form of IPC available to SymbianOS processes involves sharing handles to kernel-side objects. A number of these objects share a common interface because they derive from the same base class: RHandleBase. Examples of these objects include RChunk, RSemaphore, RMutex, and RSessionBase.

RChunk references a chunk of memory and is useful for transferring large amounts of data between processes. In previous versions of SymbianOS, this could not be used securely. An RChunk object could either be created locally, accessible only to the current process, or created as a named global object, accessible to any process that knew the name. With the introduction of 9.x, anonymous global chunks were introduced. These objects were accessible between processes, but the creating process had to pass the handle to the consuming process through the client/server interface. This greatly limited the possibility of unintentionally leaking data through a global handle; however, one still needs to take care because a shared handle can be shared further to other processes.

This same interface is exposed for the other RHandleBase-derived classes. They can be created locally, named globally, or anonymous globally. This allows a process to carefully control access to these kernel-side handles. In fact, it is this interface exposed by the RSessionBase that allows for separate processes to share file handles. A session handle to the file server is shared between two processes.

Other  
  •  Mobile Application Security : SymbianOS Security - Permissions and User Controls
  •  Windows Phone 7 Development : Building a Trial Application (part 3) - Verifying Trial and Full Mode & Adding Finishing Touches
  •  Windows Phone 7 Development : Building a Trial Application (part 2) - Connecting to a Web Service & Adding Page-to-Page Navigation
  •  Windows Phone 7 Development : Building a Trial Application (part 1) - Building the User Interface
  •  jQuery 1.3 : Table Manipulation - Sorting and paging (part 2) : Server-side pagination & JavaScript pagination
  •  jQuery 1.3 : Table Manipulation - Sorting and paging (part 1) : Server-side sorting & JavaScript sorting
  •  Windows Phone 7 Development : Understanding Trial and Full Modes (part 3) - Simulating Application Trial and Full Modes
  •  Windows Phone 7 Development : Understanding Trial and Full Modes (part 2) - Using the Marketplace APIs
  •  Windows Phone 7 Development : Understanding Trial and Full Modes (part 1) - Using the IsTrial Method
  •  Mobile Application Security : SymbianOS Security - Application Packaging
  •  
    Top 10
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
    - Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
    - Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
    - Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
    - Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
    REVIEW
    - First look: Apple Watch

    - 3 Tips for Maintaining Your Cell Phone Battery (part 1)

    - 3 Tips for Maintaining Your Cell Phone Battery (part 2)
    programming4us programming4us
    programming4us
     
     
    programming4us