COM provides two mechanisms to secure calls. The first is done automatically by the COM infrastructure. If the application provides some setup information, COM will make all the necessary checks to secure the application’s objects. This automatic mechanism does security checking for the process, not for individual objects or methods. The second is a set of functions and interfaces that applications may use to do their own security checking, and provide more fine-grained security. Furthermore, the two mechanisms are not exclusive: an application may ask COM to perform automatic security checking and also perform its own.
COM call security services are divided into three categories:
If you are using the default security values for a process for authentication and authorization, no security initialization call is necessary. If, however, you want to set other values for that process, you would call CoInitializeSecurity. This both initializes and registers these values. The values set in this call then become the default values for that process. The proxy interfaces allow the client to control the security on calls to individual interfaces.
The IClientSecurity interface is implemented locally to the client by the interface remoting layer. The client calls its methods to control the security of individual interface proxies on the object prior to making a call on one of the interfaces. Generally, clients using the default implementation instead call the helper functions that access that implementation and simplify the code: CoQueryProxyBlanket, CoSetProxyBlanket, and CoCopyProxy. Calling IClientSecurity directly is slightly more efficient then calling the helper functions. IClientSecurity works with all authentication services (NTLMSSP, DEC, kerberos). Some custom marshalled objects might not support IClientSecurity.
The server APIs and interfaces allow the server to retrieve security information about a call and to impersonate the caller. The IServerSecurity interface is implemented for all providers, but may be absent for some custom-marshaled interfaces. Helper functions are also available that rely on the IServerSecurity interface implementation: CoQueryClientBlanket, CoImpersonateClient, and CoRevertToSelf.
In a typical scenario, the client queries an existing object for IClientSecurity, which is implemented locally by the interface remoting layer. The client uses IClientSecurity to control the security of individual interface proxies on the object prior to making a call on one of the interfaces. When a call arrives at the server, the server may call CoGetCallContext to retrieve an IServerSecurity interface. IServerSecurity allows the server to check the client’s authentication and to impersonate the client, if needed. The IServerSecurity object is valid for the duration of the call. CoInitializeSecurity allows the client to establish default call security for the process, avoiding the use of IClientSecurity on individual proxies. CoInitializeSecurity allows a server to register automatic authentication services for the process.
Implementations of QueryInterace must never check ACLs. COM requires that an object which supports a particular IID always return success when queried for that IID. Aside from the requirement, checking ACLs on QueryInterface does not provide any real security. If client A legally has access to interface IFoo, A can hand it directly to B without any calls back to the server. Additionally, OLE caches interface pointers and will not call QueryInterface on the server every time a client does a query. For more information on implementing QueryInterface, see Rules for Implementing QueryInterface.
Machine administrators and the system only have full access to the portion of the registry that contains the default machine-wide call security settings. All other uses have read access only. These named values are used for classes that do not call CoInitializeSecurity, and are as follows:
To set access to objects of a specific class, there is the single named-value, AccessPermission