Symbian OS Platform Security/06. How to Write Secure Plug-ins
6 How to Write Secure Plug-ins by Mark Shackman 6.1 What Is a Secure Plug-In? Working with Symbian OS means, in many cases, working with plug-ins and frameworks. This applies to all programs that use the Application Architecture or the UIKON GUI framework. It also includes more specialized programming, including printer driver and device driver implementation and implementing new protocols to extend the networking subsystem. 6.1.1 Overview of Frameworks and Plug-ins Frameworks are a familiar and integral part of Symbian OS which, like other modern object-oriented operating systems, uses them extensively. A framework is a software system that defines a collection of abstract base classes and ready-made concrete classes, and which is designed for extension. A component will use a framework to broaden its functionality by means of extensions to the framework known as plug-ins. These are classes that derive from interfaces defined by the framework (see Figure 6.1) and which can be loaded by the framework as required at run-time. Further details of frameworks and plug-ins can be found in [Stichbury 2005] and are also touched on in [Harrison 2004]. To extend the framework, a programmer derives a new implementation from its abstract base classes and provides new behavior where required. Using plug-ins provides a number of benefits: • The design is architecturally and functionally flexible. • The client does not need to know about the detailed workings of the plug-in. • Plug-in dependencies are dynamic rather than static, so don’t need to be known at build time. 112 HOW TO WRITE SECURE PLUG-INS Client Framework Plugin 1. requests implementation 2. selects correct implementation 3. instantiates implementation 4. returns implementation interface 5. uses interface Figure 6.1 Framework Operation • Richer functionality is possible by enabling integration with third-party add-on software. 6.1.2 Security Considerations for Plug-ins A number of security issues arise when using a plug-in architecture. For example, consider an application that is authorized to access a bank account. If the application also supports plug-ins, how can it know that the plug-ins can also be trusted with access to your account? Conversely, consider a case where a plug-in implements some kind of access control to protect content on your mobile phone. How does the plug-in ensure that an application that calls it has the right to access that data? Permitting an untrusted application to gain access to the data could compromise the integrity of the system or the privacy of the mobile phone user. It is considerations such as these which necessitate plug-ins being carefully designed in order to properly integrate with the platform security architecture. This section discusses the related issues that plug-in developers need to be aware of. 6.1.3 Plug-in Mechanism Considerations When an application loads a DLL, it does so within the context of its own process. This allows the DLL to run with the same privileges and access rights as the application, and to have full access to its memory space. WHAT IS A SECURE PLUG-IN? 113 Therefore, to maintain security, the capabilities of a DLL are checked by the loader to ensure that it possesses (as a minimum) all the capabilities that the owning application process has. If it does not, the load will be unacceptable and will fail. This has important consequences for plug-ins that determine whether they should be implemented as DLLs to be loaded by the calling application. If this mechanism is used, it is necessary to ensure that the plug-in possesses at least the same set of capabilities as the process that loads it. A problem arises when the plug-in doesn’t know which process might load it and, therefore, cannot know what capabilities it will be required to possess. Implementers of plug-in frameworks, consequently, have two choices when deciding which capabilities plug-ins should be trusted with. Application-specific Plug-ins DLL plug-ins can be designed for a particular application or process. In this case, the plug-in can be given the exact capabilities required by that process, so that it can be guaranteed that the process will be able to successfully load the plug-in. This works well where the plug-in is dedicated to a specific application and each has complete trust in the other. Within Symbian OS, this technique can be seen in recognizers loaded by AppArc (the application architecture server) and rasterizers loaded by the Font and Bitmap server. However, application-specific plug-ins have two drawbacks. The obvious one is that tying the plug-in to the application prevents the plug-in from being used by other applications with different capabilities, potentially restricting its marketability and leading to wastage in ROM code if the same plug-in is needed by two applications with different capability requirements. Another drawback occurs when the application is upgraded to use additional capabilities – the plug-in will no longer be loadable as it doesn’t possess the new capabilities. General Purpose Plug-ins The other approach is to make the plug-in general purpose. This can be achieved by giving a DLL the maximum possible set of capabilities, to ensure that it can be successfully loaded by all applications regardless of their precise set of capabilities. For system plug-ins, which are assumed to be highly trusted, granting them capabilities of All -Tcb achieves this, but this option isn’t available to most third-party plug-ins for which the capabilities assigned must be carefully selected and tested. If third-party plug-ins are to be supported in a general-purpose framework, a better choice may be to design the framework to run as a secure server process (as described in Chapter 5) with a fixed set of capabilities that can be assigned to third-party DLL plug-ins. 114 HOW TO WRITE SECURE PLUG-INS 6.1.4 Plug-in Functionality Restrictions Capability Restrictions The introduction of platform security into Symbian OS has meant that plug-ins, previously able to access any API on the mobile phone, now only have access to those APIs which are not protected by capability, plus those capability-protected APIs for which the plug-in has been given the required capability. An additional restriction that derives from this situation – where a plugin uses an API restricted by capability – is that not only does the plug-in need the extra capability, but the process that loads it will also need to have the capability, or the call to the capability-protected API will fail. Data-Caging Restrictions Data caging restricts the parts of the filing system that are visible to an application or process, ensuring that one process doesn’t have access to another’s data or memory. These restrictions are inherited by the process’s plug-ins, so that a plug-in can see and manipulate only those files owned by the process that loaded it. For application-specific plug-ins, this is restrictive to the extent that the plug-in may be prevented from doing something that is its primary function (e.g. reading a database owned by another application). In such cases, it is clear that implementing the plug-in as a DLL alone is untenable and that the developer must look for other ways to support plug-ins in their applications. 6.2 Writing Secure Plug-ins 6.2.1 The ECOM Framework Before Symbian OS v7 was released, the platform contained a number of frameworks, all of which operated independently. Each framework used its own code to identify the plug-ins which were relevant to it, and to load or unload the plug-ins, as required. In Symbian OS v7, in order to gain savings in simplicity, code size and maintenance, a generic extensible framework, ECOM, was introduced. ECOM is a broad framework for specifying plug-in interfaces, and for calling and writing plug-ins. Most Symbian OS frameworks have been re-designed to use ECOM and now delegate finding and instantiating suitable plug-in objects to ECOM, rather than managing these tasks themselves with their own proprietary code. For example, in the old scheme, CONE (the graphical interaction framework) searched for available front-end processors (FEPs) and loaded WRITING SECURE PLUG-INS 115 or unloaded them on the basis of their file names. In Symbian OS v7 and later, each FEP is an ECOM plug-in, and CONE queries ECOM to get a list of the FEPs that are available to the system. ECOM has been further enhanced to be aware of platform security in Symbian OS v9. When a client requests ECOM to find suitable plug-in objects via the ListImplementations() method, ECOM filters out any plug-ins that have insufficient capabilities to be loaded by the client. Similarly, calls to CreateImplementation(), which instantiates a specified interface implementation, will fail if the requested plug-in has insufficient capabilities. Details of the ECOM architecture have been published previously. In particular, see Chapter 14 of [Stichbury 2005]. The following sections assume understanding of the basic architecture of an ECOM plug-in, concentrating primarily on the changes required by platform security. 6.2.2 Writing ECOM Plug-ins for Symbian OS v9 This section looks at the differences developers need to be aware of when designing and writing new plug-ins for Symbian OS v9 and later. Data Caging Plug-in files are stored in new locations, to comply with data-caging requirements. The DLL plug-in file, in common with other binaries, is now stored in the directory \sys\bin, which can only be read or written by processes with special capabilities. Plug-ins in the old location (\system\libs\plugins) will no longer be recognized by the security-enabled ECOM. RSC resource files for the plug-in are both moved and renamed. Their new location is in the \resource\plugins directory on each drive. The name of the resource file has also been updated, so that the resource file for a plug-in is renamed to match the DLL plug-in file name. So, for example, in Symbian OS v8.1 and earlier, the JPEG plug-in would have been delivered as: \system\libs\plugins\JPEGCodec.dll \system\libs\plugins\101F45D6.rsc In Symbian OS v9 these file paths become: \sys\bin\JPEGCodec.dll \resource\plugins\JPEGCodec.rsc 116 HOW TO WRITE SECURE PLUG-INS Plug-ins Loaded in the Client Process ECOM now loads the plug-in DLL in the client process that creates the interface implementation, so that the capabilities of the client are used when loading the plug-in. A consequence of this is that the client process now has the responsibility to release memory and unload plug-ins that are no longer in use (a task managed by the ECOM server in earlier versions of Symbian OS). This is achieved with the client-side API REComSession::FinalClose(), which was introduced in Symbian OS v7.0s but had no effect prior to Symbian OS v9. Client code using the call can therefore be used unchanged on all OS versions from v7.0s onwards. Executables using ECOM (whether servers, applications or test programs) now need to call FinalClose() as one of the last statements in E32Main() on process shutdown to complete the final cleanup. MMP Files for ECOM Plug-ins Some changes have been made to the build tools to remove locationdependent information, due to the need to install files in different locations. This allows developers to maintain a common code base for plug-in projects intended to run on Symbian OS v8.1 and later. The new syntax used in MMP files is discussed in the next section. 6.2.3 Migration of ECOM Plug-ins Plug-ins written for previous versions of Symbian OS need some minor changes to enable them to conform to the syntax of MMP files which run under platform security, as discussed in Section 6.2.1. Changes needed to the plug-in project’s MMP file are as follows: • TARGETTYPE changes from ECOMIIC to PLUGIN, to specify that the project is an ECOM plug-in. • TARGETPATH statement is removed (this is now determined by the build tools depending on the TARGETTYPE). • RESOURCE statement changes to a START RESOURCE, END block, to build the ECOM resource file. The TARGET statement is used to ensure that the built resource file has the same name (without extension) as the plug-in file name. (Symbian OS v9 requires that the built resource file name matches that of the plug-in file name.) If there are other resource files generated from the same MMP which use a TARGETPATH statement to build to a specific location, it will be necessary WRITING SECURE PLUG-INS 117 to convert the RESOURCE statements to START RESOURCE, END blocks each with a TARGETPATH statement inside, to limit the scope. These changes are illustrated in the example MMP file below: // EComExample.mmp (before) // EComExample.mmp (after) TARGET EComExample.dll TARGET EComExample.dll TARGETPATH \System\Libs\Plugins TARGETTYPE ECOMIIC TARGETTYPE PLUGIN UID 0x10009D8D 0x10009DB1 UID 0x10009D8D 0x20000B62 VENDORID 0x70000001 CAPABILITY All -Tcb SOURCEPATH ..\example SOURCEPATH ..\example SOURCE example.cpp main.cpp SOURCE example.cpp main.cpp USERINCLUDE ..\example USERINCLUDE ..\example SYSTEMINCLUDE \epoc32\include SYSTEMINCLUDE \epoc32\include SYSTEMINCLUDE \epoc32\include\ecom SYSTEMINCLUDE \epoc32\include\ecom RESOURCE 10009DB1.rss START RESOURCE 0x20000B62 TARGET EComExample.rsc END LIBRARY euser.lib LIBRARY euser.lib LIBRARY ECom.lib LIBRARY ECom.lib Note that the firstUID specified (theUID2 value) should be 0x10009D8D, which is common for all ECOM plug-ins. Further details for migrating particular types of plug-in are given in Section 6.3. 6.2.4 ROM-only ECOM Resolver Applications can differentiate between plug-ins provided on read-only media and those on read–write media by using the ROM-only resolver. This allows them to retrieve or create only legitimate ‘built-in’ plug-in implementations and ignore plug-ins that either aren’t in the ROM, or are not upgrades to ROM-based plug-ins. Allowing plug-in users to make the differentiation provides them with some level of protection from unauthorized implementations of a built-in interface. To use the ROM-only resolver, the resolver UID KRomOnlyResolverUid (defined in ECom.h) should be specified in the aResolverUid parameter of the ListImplementationsL() and CreateImplementationL() APIs of REComSession. 118 HOW TO WRITE SECURE PLUG-INS 6.3 Plug-in Implementation Considerations 6.3.1 Front-End Processors A front-end processor (FEP) allows users to input characters that aren’t directly available on a mobile phone’s keypad. In Symbian OS, different types of input (such as handwriting recognition, an on-screen virtual keyboard or predictive text entry) are provided by plug-in DLLs that implement the FEP interface. Before Symbian OS v9, CONE searched for available FEPs and loaded or unloaded them on the basis of their file names. In the secure platform, each FEP is an ECOM plug-in, and CONE queries ECOM for the system’s available FEPs. This section outlines how to migrate an existing FEP to work in Symbian OS v9. Project File Changes The MMP file needs to follow the format described in Section 6.2.3, including the specification of an ECOM resource file. Resource File This file specifies the interface UID (identifying the plug-in scheme) and the implementation UID (identifying the individual plug-in). For FEPs, the ECOM interface UID 0x1020233F must be used to ensure that the FEP will be loaded by CONE. An example FEP resource file follows:
- include <RegistryInfo.rh>
RESOURCE REGISTRY_INFO r_registry { dll_uid = 0x20000B63; // UID3 of DLL interfaces = { INTERFACE_INFO { interface_uid = 0x1020233F; // Same for every FEP implementations = { IMPLEMENTATION_INFO { implementation_uid = 0x20000B64; version_no = 1; display_name = "FEPName"; default_data = ""; } }; } }; } PLUG-IN IMPLEMENTATION CONSIDERATIONS 119 Source Code Changes There have been some changes to the FEP classes in Symbian OS v9. Please refer to the Symbian OS Library documentation on the FEPBASE application framework for further information. 6.3.2 Recognizers A recognizer is a plug-in DLL that examines the data in a file or a buffer and, if it recognizes the specific type it is looking for, returns its data, or MIME, type. Since each recognizer looks for a single MIME type, the Application Architecture (AppArc) server loads a set of recognizer plugins, each of which examine the data until one recognizes it and returns its type. Once the data type has been established, the correct application for processing that MIME type can be run. Prior to Symbian OS v9, AppArc contained its own code to detect and load recognizers; now, however, it uses the ECOM framework to do this. Recognizers are therefore subject to the same capability constraints as other ECOM DLL plug-ins and have to have the correct capabilities in order to be loaded by the AppArc server. This section outlines how to migrate an existing data recognizer to work in Symbian OS v9. Project File Changes The MMP file needs to follow the format described in Section 6.2.3 including the specification of an ECOM resource file. Resource File For data recognizers, the ECOM interface UID 0x101F7D87 must be used. For example:
- include <RegistryInfo.rh>
RESOURCE REGISTRY_INFO r_registry { dll_uid = 0x20000B65; // UID3 of the DLL interfaces = { INTERFACE_INFO { interface_uid = 0x101F7D87; // For all data recognizers implementations = { IMPLEMENTATION_INFO { implementation_uid = 0x20000B66; 120 HOW TO WRITE SECURE PLUG-INS version_no = 1; display_name = "DataRecognizerName"; default_data = ""; } }; } }; } Source Code Changes This section describes the source code changes needed for a data recognizer. An example header file would appear as: class CExampleDataRecognizer : public CApaDataRecognizerType { public: static CApaDataRecognizerType* CreateRecognizerL(); }; In the CPP file, the previously exported CreateRecognizerL() function should be removed and replaced by:
- include <ImplementationProxy.h>
const TInt KExampleDataRecognizerImplementationUID = 0x20000B66; . . . CApaDataRecognizerType* CExampleDataRecognizer::CreateRecognizerL() { return new (ELeave) CExampleDataRecognizer (); } const TImplementationProxy ImplementationTable[] = { IMPLEMENTATION_PROXY_ENTRY(KExampleDataRecognizerImplementationUID, CExampleDataRecognizer::CreateRecognizerL) }; EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) { aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); return ImplementationTable; } 6.3.3 Control Panel Plug-ins Different control panel plug-ins are likely to need different capabilities in order to change the mobile phone’s configuration. Rather than each plugin running in a parent process with a dangerously large set of capabilities, PLUG-IN IMPLEMENTATION CONSIDERATIONS 121 in Symbian OS v9 each plug-in runs in its own process, so that each can have the minimum set of capabilities that it requires. For this reason, all existing control panel plug-ins, which were implemented as polymorphic DLLs, now become standard applications, but with a special registration file. This registration file is used by the application server to distinguish the plug-in from a normal application. This section outlines how to migrate an existing control panel plug-in to work in Symbian OS v9. Prerequisites • The control panel application should be located in \sys\bin\ <appname.exe>. • The control panel application’s UI resource file should be located in \Resource\apps\<appname.rsc>. • There should be a registration resource file for each control panel application in \private\10003a3f\apps\ if it is either on the emulator or built into the ROM, or \private\10003a3f\import\apps\ if it is installed via Software Install. • For control panel applications, a byte in the registration resource file must be explicitly set to indicate that it is a control panel application. Project File Changes The MMP file will need changes to build the plug-in as an EXE rather than a DLL. These are the same changes as apply to converting any application from versions prior to Symbian OS v9, as applications were previously themselves DLL plug-ins to the Application Architecture framework. Source Code Changes The control panel plug-in will require some source code changes in order to run as a separate application rather than a DLL. There are however no changes needed specifically relating to control panel functionality. 6.3.4 Converting DLL Plug-ins to Servers Using DLLs can have limitations due to the changes brought in for platform security. Where the default security model offered by the loader may not be appropriate for the intended use of a plug-in, it may be necessary to address it by moving to a client–server model. It is important to note, however, that any security issues causing amismatch between the capabilities of the client and the plug-in will not have gone away, and will 122 HOW TO WRITE SECURE PLUG-INS Before After ECOM DLLs ECOM DLLs Server EXEs Application Plug-in 1 Impl 1 Plug-in 2 Impl 2 Plug-in 3 Impl 3 { Application Proxy Proxy Proxy { Glue Impl 1 Glue Impl 2 Glue Impl 3 { Glue Glue Glue IPC Boundary Client side Server side Figure 6.2 Converting Plug-ins to a Client–Server Architecture have to be addressed by both the client and the server implementations in order to avoid introducing security weaknesses (see Chapter 5 for further details on client–server security). This section covers how to implement an ECOM plug-in as a server process, with some ‘glue’ code that all subsequent plug-ins that implement the same interface can reuse. Thus the aim is to effect the transition shown in Figure 6.2. As shown, the implementation part of the plug-in is replaced with a proxy, which acts as the plug-in. Rather than manufacture the original implementation, the proxy manufactures a client-glue version and a server. The client-glue code then marshals any required parameters and delivers them to the server. The server takes the parameter data and invokes the call on the real implementation. Any results returned by the server are marshaled by the server-glue code and returned to the client glue which takes them and returns them to the calling application. Note that the client-glue and server-glue code is the same for each plugin and is linked into each ECOM plug-in DLL and server implementation. We must emphasize the importance of addressing the security issues that will arise from introducing a mechanism where the plug-in may be less trustworthy than the client application (in which case the client-glue code must be responsible for ensuring that sensitive data is not provided to the server) or the client application may be running with less capability than the plug-in (in which case the server-glue code must be responsible for ensuring that sensitive data or services are not provided to the client). Chapter 5 presents some mechanisms that can be used to perform such security checks, including the CPolicyServer class. PLUG-IN IMPLEMENTATION CONSIDERATIONS 123 Replacing the Plug-in with a Proxy All ECOM DLL plug-ins contain a mandatory part, which provides ECOM with a table of implementation UIDs and constructors. Typically, this would look like: const TImplementationProxy ImplementationTable[] = { IMPLEMENTATION_PROXY_ENTRY(0x2000BAE, CMyPlugIn1Factory::NewL) } /** Lookup method required by ECom. Returns the above table to the ECom framework */ EXPORT_C const TImplementationProxy ImplementationGroupProxy(TInt& aTableCount) { aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); return ImplementationTable; } In the ImplementationTable structure, the UID used is unique to this particular implementation and matches the UID specified in the plug-in’s resource file. The file is changed so that ECOM now returns a proxy object that is of the same type but returns different products. Note that the proxy takes a server name, MyPlugin1FactoryServer, which is propagated down into client-glue calls to ensure that calls go to the correct server. These changes are seen below: // The name of the corresponding server of this ECOM plug-in _LIT(KServerName, "MyPlugin1FactoryServer"); static CMyPlugIn1Factory* CreateProxyL() { return CreatePlugInFactoryProxyL(KServerName); } const TImplementationProxy ImplementationTable[] = { IMPLEMENTATIONPROXYENTRY(0x2000BAF, ::CreateProxyL) }; EXPORTC const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) { aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); return ImplementationTable; } 124 HOW TO WRITE SECURE PLUG-INS Client Glue Code Usually the plug-in objects carry out the required processing, but these have been replaced with a proxy, CPlugInFactoryProxy, which produces proxy objects, such as CPlugInHandlerProxy. The proxy code in CPlugInHandlerProxy reveals what is going on instead: void CPlugInHandlerProxy::ConstructL(const TDesC& aServerName, const TDesC& aFileName) { User::LeaveIfError(iSession.Connect(aServerName)); // Send the command to construct a handler // Param 0: [OUT] TDesC16 - file name iSession.SendRequestL(ECreateHandler, TIpcArgs(&aFileName)); } void CPlugInHandlerProxy::DataSizeL(TInt &aSize) { // Client-server parameters // Param 0: [IN] TPkg<TInt> - size TPckg<TInt> sizePkg(aSize); iSession.SendRequestL(EDataSize, TIpcArgs(&sizePkg)); } TInt CPlugInHandlerProxy::ProcessData(TInt aResult) { // Client-server parameters // Param 0: [OUT] TInt - result return iSession.SendRequest(EProcessData, TIpcArgs(static_cast<TInt>(aIntent))); } The above code shows that: • when the CPlugInHandlerProxy was created, a session was established with a server. The first message sent by the new session is one requesting the server to create a corresponding handler on the server side • the method functions are not performing any real processing, but are simply marshaling parameter data into requests on the session • data is being copied and cannot be passed by reference. Only simple data types are used here – complex data types could be handled by storing them in shared buffers. If this is required, the data types must support ExternalizeL and InternalizeL operations if they are to be handled by client–server glue code. Method functions (e.g. EProcessData) are represented by enumerations, which are common to both client and server). This, along with PLUG-IN IMPLEMENTATION CONSIDERATIONS 125 the methods in the proxies, is why the client and server glue code must be tailored for a particular ECOM interface, but can be reused without change across all plug-ins, except for the specification of the server name. The proxy object CPlugInHandlerProxy would employ an RSessionBase- derived object. On Connect(), this object handles the transparent start up of the server, if it does not already exist. Server-Glue Code The server example implementation code below shows a server being created, and also being given the real (non-proxy) CMyPlugIn1Factory constructor that used to be returned by our original client-side ECOM implementation before we replaced it with a proxy.
- include "startserver.h"
_LIT(KServerName, "MyPlugin1FactoryServer"); // E32Main calls StartServer with the server // name and the factory construction function TInt E32Main() { return StartServer(KServerName, CMyPlugIn1Factory::NewL); } Note that this is also specific to a particular ECOM interface, and that the server name ties in with the name used on the client side. StartServer() creates an implementation of the standard Symbian OS CServer2 class which will create sessions when required. These sessions provide a standard ServiceL() interface, which creates message handlers, based on the method function identifier passed in the RMessage2 message. When the session starts, a message handler is created if one doesn’t already exist. This server behavior is triggered by the use of the proxy objects on the client side, for example when CPlugInHandler- Proxy::ConstructL() is invoked, an ECreateHandler message is propagated to the server so that the relevant handler can be created. void CPlugInSession::ServiceL(const RMessage2& aMessage) { if (!iMessageHandler) { // Create the new message handler based on the message code switch(aMessage.Function()) { case ECreateHandler: iMessageHandler = CServerHandler::NewL(iServer.Factory(), aMessage); break; 126 HOW TO WRITE SECURE PLUG-INS default: // Panic - invalid message aMessage.Panic(KServerGluePanic, EServerGlueInvalidMessage); break; } } else { // If the message handler has already been created, // then delegate the request iMessageHandler->ServiceL(aMessage); } } The message handler’s role is to: • create a real implementation of the required interface (not a proxy) • based on the incoming message’s ’method’ parameter: ◦ unmarshal the parameters from the message ◦ invoke the ’real’ implementation ◦ marshal any responses. 6.3.5 Writing New ECOM-based Plug-in Frameworks Prior to Symbian OS v9, to identify all the polymorphic DLLs that were available for them to load, a framework used to search a directory (or directories) and examine any DLLs it found, checking the UID2 and UID3 for specific values. With platform security, all binaries are located in \sys\bin\, and only processes with the AllFiles capability are able to read from that location. This means that most processes will not be able to scan for binaries themselves. By ensuring that DLL plug-ins are changed into ECOM plug-ins, developers of new frameworks, or those migrating older ones, can implement them as standard ECOM frameworks and thereby utilize the functionality provided by the ECOM server to discover and load appropriate plug-ins. As discussed previously, the capabilities of any plug-in intended to be loaded in the framework would have to be considered, to ensure that they can be successfully loaded. Obligations on Framework Developers As previously discussed, framework developers must ensure that they handle calls to FinalClose() in a graceful fashion as part of their framework termination code. SUMMARY 127 ECOM Custom Resolvers A default resolver that selects an implementation to use is provided as part of ECOM. Custom resolvers are commonly provided by large frameworks that define and utilize many ECOM interface classes to provide framework-specific resolution rules for selecting and retrieving implementations. These resolver plug-ins are loaded into the ECOM server process and thus require a high level of trust. Custom resolvers are themselves interface implementations that implement the ECOM CResolver interface. They are instantiated by ECOM as required, in response to REComSession::CreateImplementation- L() and REComSession::ListImplementationsL() calls that specify a particular custom resolver to use. Custom resolvers must conform to other aspects of interface implementations, including providing registration resource information and publishing their UID and factory functions in an implementation proxy table. Under platform security, the ECOM server is protected, with the server executable having the ProtServ capability. The server can therefore only load resolver DLLs that have been trusted with the ProtServ capability, which will normally require a signature from a trusted authority. Custom resolvers developed for earlier releases of Symbian OS will need to be rebuilt and signed to allow them to work with the platform security version of ECOM. 6.4 Summary This chapter explains the effect that the introduction of platform security has had on plug-ins and frameworks, including security issues relating to the use of plug-in DLLs. First we covered the definition of a plug-in, including the distinction between a plug-in designed for a specific application, which can have precisely targeted security capabilities, and general purpose plug-ins which potentially need to be trusted with a wide range of capabilities. Then we examined the use of the ECOM plug-in framework within the platform security architecture, including new locations for plug-in files and security considerations resulting from the plug-in DLL running in the client application’s process. We also covered the ability to restrict the selection of ECOM plug-ins to those built-in to the phone ROM. Finally we discussed some implementation considerations, including how to migrate plug-ins written for previous Symbian OS versions, how to implement a plug-in using a client–server architecture when more sophisticated security controls are needed, and how to implement new plug-in frameworks using ECOM.