DCOM can make distributed applications secure without any security specific coding or design in either the client or the component. Just like the DCOM programming model hides a component's location, it also hides the security requirements of a component. The same (preexisting or off-the-shelf) binary code that works in a single-machine environment, where security may be of no concern, can be used in a distributed environment in a secure fashion.
For more information about DCOM in general, see the DCOM Technical Overview and DCOM Architecture white papers. This section will try to summarize how DCOM security features are layered on the Windows SSPI.
There are two distinguishable categories of security provided by Distributed COM. The first form is termed Activation Security, and it controls which objects a client is allowed to instantiate. The second form is Call Security, which dictates how security operates at the per-call level between an established connection from a client to an object (server). Activation security controls which classes a client is allowed to launch and retrieve objects from.
DCOM provides two mechanisms to secure calls. The first mechanism DCOM provides is APIs and interfaces that applications may use to perform their own security checking. The second mechanism is done automatically by the DCOM infrastructure. An important item to note is the automatic mechanism does security checking for the process, not for individual objects or methods.
Since DCOM security is layered on secure RPC, there are frequent references to constants defined for RPC-level interfaces. The section below on Using Secure RPC shows how the RPC constants map to SSPI security provider features.
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.
An example illustrating a specific use of the IClientSecurity interface would be to ensure the integrity and privacy of a credit card transaction; you may want to utilize the IClientSecurity interface to escalate the RPC authentication level to include packet encryption (RPC_C_AUTHN_LEVEL_PKT_INTEGRITY).
Although DCOM provides default security levels for authentication, the client requests additional features using IClientSecurity::SetBlanket to define the security level required. The definition of IClientSecurity::SetBlanket is shown below.
HRESULT IClientSecurity::SetBlanket(pProxy, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities );
This method sets the authentication information that will be used to make calls on the specified proxy. The values specified here override the values chosen by automatic security. Calling this method changes the security values for all other users of the specified proxy.
The arguments for IClientSecurity::SetBlanket are the following:
Argument |
Type |
Description |
pProxy |
void* |
This parameter indicates the proxy to set. |
dwAuthnSvc |
DWORD |
A single value from the list of RPC_C_AUTHN constants indicating the authentication service to use. It may be RPC_C_AUTHN_NONE if no authentication is required. |
dwAuthzSvc |
DWORD |
A single value from the list of RPC_C_AUTHZ constants indicating the authorization service to use. If you are using the Windows NT authentication service, use RPC_C_AUTHZ_NONE. |
pServerPrincName |
WCHAR* |
Indicates the server principal name to use with the authentication service. If you are using RPC_C_AUTHN_WINNT, the principal name will be ignored. |
Argument |
Type |
Description |
dwAuthnLevel |
DWORD |
A single value from the list of RPC_C_AUTHN_LEVEL constants indicating the authentication level to use. |
dwImpLevel |
DWORD |
A single value from the list of RPC_C_IMP constants indicating the impersonation level to use. Currently, only RPC_C_IMP_LEVEL_IMPERSONATE is supported. |
pAuthInfo |
RPC_AUTH_IDENTITY_HANDLE* |
Establishes the identity of the client. It is authentication service specific. Some authentication services allow the application to pass in a different user name and password. COM keeps a pointer to the memory passed in until COM is uninitialized or a new value is set. If NULL is specified COM uses the current identity (whether it is the process token or impersonation token). |
dwCapabilities |
DWORD |
Flags to establish indicating the further capabilities of this proxy. Currently, no capability flags are defined. |
Returns |
S_OK |
Success. |
E_INVALIDARG |
One or more arguments is invalid. |
By default DCOM will choose the first available authentication service and authorization service available on both the client and server machines and the principal name which the server registered for that authentication service. Currently, DCOM will not try another authentication service if the first fails.
The arguments allow the client application to select a specific authentication service and authentication level. The available values for these arguments are shown below in Table 1: RPC Authentication Service Identifiers and Table 2: RPC Authentication Levels and SSP Services. The default Windows NT authentication service uses the NTLM security support provider. Future versions of Windows NT will make available additional authentication services based on Kerberos and SSL.
When a call arrives at the server, the server may call CoGetCallContext to retrieve a IServerSecurity interface which 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.
The IServerSecurity interface is used by a server to help identify the client and is also used to impersonate the client during a call. By calling IServerSecurity::ImpersonateClient, the server can impersonate a client for the duration of the call. One should note that CoImpersonateClient is a helper function that calls CoCallGetContext in order to retrieve an IServerSecurity interface pointer and then it calls IServerSecurity::ImpersonateClient.
The IServerSecurity::ImpersonateClient maps through the RPC run time layer to the SSPI call ImpersonateSecurityContext.
This method allows a server to impersonate a client for the duration of a call. The server may impersonate the client on any secure call at the identify, impersonate, or delegate level. At the identify level, the server may only find out the clients name and perform ACL checks; it may not access system objects as the client. At delegate level the server may make off machine calls while impersonating the client. The impersonation information only lasts until the end of the current method call. At that time IServerSecurity::RevertToSelf will automatically be called, if necessary.
This method restores the authentication information on a thread to the process's identity.
The server may impersonate the client on any secure call at the identify, impersonate, or delegate level. At the identify level, the server may only find out the clients name and perform Access Control List (ACL) verification; it may not access system objects as the client. At the delegate level the server may make service calls on behalf of the client to servers on different machines. The impersonation information only lasts until the end of the current method call. At that time IServerSecurity::RevertToSelf will automatically be called if necessary.
The following helper routines are available to support DCOM server impersonation.
Allows the server to impersonate the client of the current call for the duration of the call. This function will fail unless the object is being called with RPC_C_IMP_LEVEL_IMPERSONATE or higher impersonation in effect. This function encapsulates the following sequence of common calls (error handling excluded):
CoGetCallContext(IID_IServerSecurity, (void**)&pss); pss->ImpersonateClient(); pss->Release();
Restores the authentication information on a thread of execution to its previous identity. This function encapsulates the following sequence of common calls (error handling excluded):
CoGetCallContext(IID_IServerSecurity, (void**)&pss); pss->RevertToSelf(); pss->Release();
The Win32 SDK contains a sample program that demonstrates the use of DCOM call security features. (The location of the DCOM secure example program in the Win32 SDK is c:\mstools\samples\ole\dcom\secure.) The SECURE sample consists of a client portion and a server portion. The purpose of the sample is to demonstrate client-side and server-side security features.
The server application, SECSVR.EXE, demonstrates the packaging options available to server writers and the call-security capabilities. It implements the following server capabilities:
The client application, SECCLNT.EXE, allows you to select security settings for the client application's connections to the server application.
DCOM uses the authentication, authorization, and message integrity capabilities of authenticated RPC. The next section looks at secure RPC services, and the APIs available to integrate security features at that level.