Client/server communication

Interprocess communication (IPC) is the basis for client/server architecture used commonly in Symbian OS. Clients and servers are contained in separate threads, although not necessarily in different processes. All services offered by the server are defined in the client-side API (often implemented as DLL), and interaction between client and server is done with a message-passing protocol. This means that there are no direct pointers between parties, leaving the integrity of the server and its resources untouched by clients.

Communication between the client and the server is managed by Interthread Communication (ITC). There is no pure IPC in Symbian OS, as the kernel ensures that ITC messages are delivered to corresponding threads, even over process boundaries. It is important to realize that message delivery is an unreliable method — messages may be lost if the server's message slots are full.

Each message consists of five 32-bit user-defined integers; the first one is a message function number, used to express the meaning of the message. There are no limitations in using this number (except a few reserved functions), so the designer of the server can freely define the functions. The remaining four integers (actually three, if the connection is being used as a subsession, because the fourth is reserved for the subsession handle) are parameters, either pure number information or a pointer to a client-side descriptor.

Decoding of the parameters is known only by the server and its clients. This is also the security feature of the client/server interface; because process boundaries are separators of memory space, direct pointers to the client's data structures cannot be delivered. All data not fitting in the provided integers must be represented as a descriptor (a flat data structure is still possible), and an address to the descriptor (or actually a TPckg object) is delivered within the message. The server then uses safe interthread read and write functions to access the provided descriptor.

The following figure shows the relationship of the TDesC and TPckg classes.

Figure 20: Relationship of a message package and a descriptor class

Several issues should be considered when implementing the client-side API:

Process identification

Sometimes it is useful for security reasons to obtain more information about a server's or application's process.

  • To verify an application's identity, developers can retrieve the application's name and UID using RApaLsSession and then compare it against known information.

  • The list of currently running applications can be found with the TApaTaskList class.

  • In platform security-enabled platforms there are two separate identifiers for applications: secure ID and vendor ID. For further details, see the Secure interprocess communication information below.

Secure interprocess communication

Almost all Symbian OS resources are implemented as servers that are run in their own processes. Therefore, it is necessary for operating system's reliability to enable secure negotiations between clients and servers residing in different processes.

Interprocess communication is designed to deliver messages over process boundaries, which also act as memory management boundaries. Message delivery and memory management are the responsibility of the kernel, making it a reliable and secure way to communicate.

Every executable has its own Secure Identifier (SID), which is used to identify the running process launched from the executable. SID is stored in the executable binary, so it has the same security as any executable code.

In addition to SID, signed applications have a Vendor Identifier (VID). Applications from one vendor usually share a common VID, but the vendor may have different VIDs for different product families. The VID is especially useful when it is necessary to limit access to an API to a certain vendor; for example, internal APIs and APIs that are being developed continuously could be limited to a particular vendor. VIDs can also be used to group servers and clients into logical groups providing services to each other.

Authentication in IPC can be done in different ways; client capabilities can be checked, either manually (run-time) or automatically (build-time). The server can also authenticate the client with SID and VID, making it possible to tailor request types and give responses individually. There is no requirement from platform security or the framework; the server can decide whether or not to request capabilities from the client. The client has more limited options available: the server is usually authenticated by name. There is a special ProtServ capability that allows the server to insert an "!" in front of its name, indicating that the server can be trusted. Nameless servers are also possible; no client can connect them unless a handle to the server is provided.

The features listed above can be merged as a security policy that every server should define. A security policy simply defines:

  • Which capabilities are required from the caller

  • Which SID and VID are required from the caller

  • What actions are possible or must be done with the information provided:

    • Can input data be trusted?

    • Is user acceptance needed for this operation?

    • Can this server act as a proxy towards other components?

The only security issue that the caller process can check is the name of the server (and associated SID or VID) that it is connecting to.