FAQ: COM Security Frequently Asked Questions

Last reviewed: December 10, 1997
Article ID: Q158508
The information in this article applies to:
  • Microsoft COM/DCOM Libraries included with: - Microsoft Win32 Software Development Kit (SDK) for Windows NT,

         version 4.0
    
    - Microsoft Win32 Software Development Kit (SDK) for Windows 95 with

         DCOM Support
    
    -----------------------------------------------------------------------

SUMMARY

The COM/DCOM security model enables the creation of secure distributed applications. COM security can be applied to both existing (legacy) COM components via external configuration as well as new COM code via the COM security APIs and interfaces. This document provides tips and techniques, as well as troubleshooting information, for developers of secure COM components.

MORE INFORMATION

Table of Contents

General COM Security Issues:

  1. How do I enable or disable DCOM?
2. Why do I get E_OUTOFMEMORY when trying to access a remote object? 3. Why doesn't IConnectionPoint::Advise work? 4. I get E_ACCESSDENIED from CoCreateInstanceEx. Why? 5. Are there any issues with running COM servers under the "system"
   account?
6. Why does CoRegisterClassObject return CO_E_WRONG_SERVER_IDENTITY? 7. Does DCOM support delegate level impersonation? 8. LocalServer32 entries with UNC names cannot be remotely activated. Why? 9. Why can't my server access network resources? 10. What are the limitations of RunAs the Launching User? 11. Should I use AccessCheck or IsValidSecurityDescriptor? 12. How can I get a log of AccessCheck failures? 13. How can I troubleshoot activation problems? 14. Why do I get a "User32.dll could not be initialized" message? 15. Why do I get a "Shell32.dll could not be initialized" message? 16. How can I troubleshoot call level problems? 17. Are there any hints on impersonation problems? 18. Why does CoCreateInstance fail in my ISAPI extension?

COM security on Windows 95:

  1. Where can I get DCOM for Windows 95?
20. Can I redistribute DCOM for Windows 95? 21. What security features are in COM on Windows 95?

Windows NT Security Issues:

  1. Where can I find more information on Windows NT Security?

General COM Security Issues

Q1. How do I enable or disable DCOM?

A. The HKEY_LOCAL_MACHINE\Software\Microsoft\OLE registry key has "EnableDCOM" as a named value. By default this value is set to "Y." To disable DCOM, change this value to "N." You can do this in the OLE/COM Object Viewer with the File.System Configuration dialog box. Changing this value requires a reboot.

If EnableDCOM is not set to "Y," then all cross-machine calls are rejected (the caller, typically, gets an RPC_S_SERVER_UNAVAILABLE return code).

On Windows 95, with DCOM support, there is an additional registry setting that enables or disables incoming remote connections. The registry key is HKEY_LOCAL_MACHINE\Software\Microsoft\OLE, and the named value is "EnableRemoteConnections." By default remote connections are disabled (the value is "N"). To enable remote connections to a Windows 95 machine, change this value to "Y." You can do this in the OLE/COM Object Viewer (OLEView) with the File.System Configuration dialog box. Changing this value requires a reboot.

Q2. Why do I get E_OUTOFMEMORY when trying to access a remote object?

A. DefaultAccessPermissions does not include the SID for the SYSTEM account. Use DCOMCNFG or the OLE/COM Object Viewer to add it.

E_OUTOFMEMORY is returned, rather than E_ACCESSDENIED, because of a bug in Windows NT 4.0. This will be fixed in future releases of DCOM.

This failure can occur both when trying to activate an object (via CoCreateInstanceEx, for example) and when receiving a pointer to a remote object (in the implementation of IConnectionPoint::Advise, for example). See the question below titled "Why doesn't IConnectionPoint::Advise work?"

The DefaultAccessPermissions value on your system is probably missing the SYSTEM SID because some versions of OLEView's System Configuration dialog box do not correctly add SYSTEM if no default value has been already provided (DCOMCNFG writes it correctly). The fix to this is to use either DCOMCNFG or OLEView and add "SYSTEM" to the list of SIDs in the Default Access Permissions.

Versions of OLEView with a build number greater than 46 (see the About box) correctly add the SYSTEM SID. OLEView is available for download from http://www.microsoft.com/oledev/.

Q3. Why doesn't IConnectionPoint::Advise work?

A. In order for IConnectionPoint::Advise, or any other interface method, which is passed an IUnknown pointer, to work correctly, it must have the appropriate access permissions to the object in order to call QueryInterface on any remote interface.

You are probably not calling CoInitializeSecurity() in your client and are thus picking up the default DCOM-supplied security blanket. The client application should initialize security such that the server process identity is allowed to call into the client process. For this, the client must call CoInitializeSecurity and specify a security descriptor containing an ACE for the server process identity with the COM_RIGHTS_EXECUTE right. If the client does not call CoInitializeSecurity, the callback into the client will be governed by the default security blanket, that is, the default authentication level and (if the former is not RPC_C_AUTHN_LEVEL_NONE) the default access permissions of the client machine.

So, since you are writing a real DCOM application, you should simply call CoInitializeSecurity() after you call CoInitalizeEx(), such as in the following example:

    hr = CoInitializeSecurity(
          NULL,                        //Points to security descriptor
            -1,                          //Count of entries in asAuthSvc
            NULL,                        //Array of names to register
            NULL,                        //Reserved for future use
            RPC_C_AUTHN_LEVEL_NONE,      //The default authentication
                                         //level for proxies
            RPC_C_IMP_LEVEL_IMPERSONATE, //The default impersonation
                                         //level for proxies
            NULL,                        //Reserved; must be set to NULL
            EOAC_NONE,                   //Additional client or
                                         //server-side capabilities
            NULL                         //Reserved for future use
            );

By doing this, you are essentially allowing anyone to call into the client process. If the server hands a reference to your sink to someone on the Moon and he tries to call back, he will get in just fine. See information on the different authn and impersonation levels in the Win32 SDK Help to figure out what settings make the most sense for your application.

Note that both Microsoft Foundation Classes (MFC) and Active Template Library (ATL) have bugs in their IConnectionPoint::Advise implementation. They both do essentially the following:

   HRESULT CConnectionPoint::Advise(IUnknown* pUnkSink, DWORD *pdwCookie)
   {
      IUnknown* p;
      HRESULT hRes = S_OK;
      if (SUCCEEDED(pUnkSink->QueryInterface(*m_piid, (void**)&p)))
      {
         // Add p to the list of sinks;
      }
      else
      {
         hRes = CONNECT_E_CANNOTCONNECT; // ATL does this
         hRes = E_NOINTERFACE; // MFC does this
      }
      return hRes;
   }

The bug is that they should return whatever the QI call returned instead of mapping to CONNECT_E_CANNOTCONNECT or E_NOINTERFACE. The correct way to implement a connection point is roughly the following:

   HRESULT CConnectionPoint::Advise(IUnknown* pUnkSink, DWORD *pdwCookie)
   {
      IUnknown* p;
      HRESULT hRes = pUnkSink->QueryInterface(*m_piid, (void**)&p);
      if (SUCCEEDED(hRes))
      {
         // Add p to the list of sinks, maybe returning
         // CONNECT_E_ADVISELIMIT if necessary
      }
      else if (hRes == E_NOINTERFACE)
      {
         // The sink does not support *m_piid!
         return CONNECT_E_CANNOTCONNECT;
      }
      return hRes;
   }


Q4. I get E_ACCESSDENIED from CoCreateInstanceEx. Why? I am an administrator on both my machine, and the second machine if that matters.

A. Windows NT security principals are identified with a two-level name made up of the security authority and then the user name. The security authority is either the workstation (for a standalone Windows NT Workstation environment) or the domain if your machine that's running Windows NT Workstation is a member of a domain (all machines running Windows NT Server are members of a domain by definition). Even when in a Windows NT Server domain, machines running Windows NT Workstation continue to be their own security authorities with (potentially) local- only accounts; however, they "trust" (are willing to pass along security requests to) the domain controls of the domain in which they reside.

For example, on a domain called "Foo" my security identity would be "Foo\MarkRy," even if I am logged on to my machine "Markry_Tecra," But if my machine is standalone (or if I choose to log on locally), my identity would be "Markry_Tecra\MarkRy," which is a completely different security principal. You can think of machines running Windows NT Workstation as being "domains of one." They either trust another NT (real) domain and refer security-related decisions regarding principals from that domain to it (in the case where they are members of a domain), or they do not (in the case of a standalone environment).

In your case, it sounds like you have two standalone machines running Windows NT Workstation and, therefore, two completely different security principals. You log on to one as Machine1\RJF, and the other as Machine2\RJF. The fact that your account on each is an admin account does not matter because they are different accounts.

Nevertheless, you can get two machines running Windows NT Workstation that are not in the same or trusting domains (and, therefore, cannot have the same principal logged on to both simultaneously) to interact securely because Windows NT Workstation falls back to a "matching account names and passwords" mode. If you use the same ASCII names on the two machines running Windows NT Workstation and the accounts have the same passwords, then DCOM and other NT security (such as filesystem) should work as though you were really logged on to the two machines with the same account.

Here are some caveats to this fallback mode:

  • This mode does not work unless both sides use local accounts, not domain accounts. For example, I could not use my Foo\MarkRy account on Machine1 and a Machine2\MarkRy account on the other machine running Windows NT Workstation. In that case, Windows NT Workstation would have to delegate to its domain controllers, which it does not do. It fails any attempts by a different MarkRy that comes from an distrusted domain (or machine running Windows NT Workstation).
  • This fallback mode is implicit in Windows NT Workstation to Windows NT Workstation interactions but explicit in interactions between Windows NT Workstation and Windows NT Server. In the case where you want to give access to an machine running Windows NT Server from a Windows NT Workstation user, but the Windows NT Workstation machine itself is not part of the same domain (or of a trusted domain), you need to create a special kind of user account called a "local" user. In the User Manager for Domains, open the New User dialog box, and click Account.

This is how Windows NT Server works with an account from a distrusted machine running Windows NT Workstation or Windows NT Server but, again, only by matching the ASCII account name and the password. "Local" accounts have various restrictions. Basically, they are never delegated for security checks, so they cannot be used in trusted domains, for example. Another significant limit is that a "local" Windows NT Server/domain account cannot be used on any of the Windows NT Workstation or non-DC Windows NT Server machines in that domain because that would also require referral (from Windows NT Workstation to Windows NT Domain Controller).

Q5. Are there any issues with running COM servers under the system account?

A. Localsystem is a very privileged account locally, so you shouldn't run any shareware applications there. However, it has no network privileges and cannot leave the machine via any NT-secured mechanism, including file system, named pipes, DCOM, or secure RPC.

Q6. Why does CoRegisterClassObject return CO_E_WRONG_SERVER_IDENTITY? When launching my ATL 1.1 server service as an .exe file, I get CO_E_WRONG_SERVER_IDENTITY from CoRegisterClassObject. (The class is configured to run as a security ID different from the caller.) This seems to happen whether or not I skip the CoInitializeSecurity. It fails running as a service or as an .exe file.

A. Many services are debugged by running them as console applications in the interactive user's identity. Since the service is already registered to run in a different identity (configurable by the Services control panel applet), OLE fails the CoRegisterClassObject and RunningObjectTable::Register(ROTFLAGS_ALLOWANYCLIENT) calls by returning CO_E_WRONG_SERVER_IDENTITY to enforce security and to prevent malicious servers from spoofing the server. To debug by running in the interactive user's identity, make the following changes in the server's registry entries to prevent these failures:

  • To prevent CoRegisterClassObject failure, remove the following named value:

    [HKEY_CLASSES_ROOT\APPID\{0bf52b15-8cab-11cf-8572-00aa00c006cf}] LocalService"="HelloOleServerService"

  • To prevent a IRunningObjectTable::Register(ROTFLAGS_ALLOWANYCLIENT) failure, use the following steps:

    1. Remove the following named value:

          [HKEY_CLASSES_ROOT\APPID\{0bf52b15-8cab-11cf-8572-00aa00c006cf}]
          "LocalService"="HelloOleServerService"
    

    2. Then add the following named value:

          [HKEY_CLASSES_ROOT\APPID\{0bf52b15-8cab-11cf-8572-00aa00c006cf}]
          "RunAs"="Interactive User"
    

Make sure that you restore the modified registry entries after debugging.

Q7. Does DCOM support delegate-level impersonation?

A. No. See question 8 for details.

Q8. LocalServer32 entries with UNC names cannot be remotely activated. Why? If I place a UNC in the LocalServer32 entry of a DCOM object, that object can no longer be launched from a remote machine. Is there a patch or workaround to this other than the one below, which compromises system security quite significantly. The problem is that DCOM is attempting to access the LocalServer32 executable from the System account (null session). If the machine on which the executable is located is configured to allow null session access, then the problem disappears. Do this by setting the following registry value to 0:

   \\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\
   Parameters\RestrictNullSessionAccess

This value is a DWORD and is documented in the "Server Service Entries" article of the DevNet CD. It requires a machine reboot to take effect. This is apparently a bug in DCOM, which should be using the RunAs key to determine how to access the server executable and impersonate that user before attempting any access.

A. It is not a bug in DCOM. Try it yourself: impersonate a user coming from a remote machine and then try any network-related operation that uses NT security. It does not work. If it did work, impersonation could form an endless chain, and allowing threads to impersonate you would be much more risky, as they could then, say, open your e-mail folder on a remote machine, change your password on the domain controllers, and so forth.

Windows NT 5.0 will support full security delegation (which is what it would take to make chaining scenarios work) but only when a few additional safeguards are in place, most notably the enforcement of *expirations* on delegated security rights (so at least you know that the right to do these kind of nasty things expires after a few minutes or whatever you set). The other safeguard would be an extension to the ACL model that would allow you to distinguish between the "real" you and your delegates--that way you could secure certain key things against code that is otherwise authorized to act as you.

Q9. Why can't my server access network resources?

A. See question 10.

Q10. What are the limitations of RunAs the Launching User? I have a dual server that accesses files on its computer via a method call, IFoo::Do(). When I deploy my server, on Windows NT 4.0 Workstation, using the default security of Launching User, file access does not work when I call my method IFoo:Do() remotely. It fails with an access permission.

I would expect identity "Launching User" if I had an administrator user on machine A and the same administrator user on machine B. Then the identity of my launched server would be that administrator user on machine B. However, it drops some rights because my file access fails. When I set the identity to RunAs with the administrator user on machine B, everything works. What is the difference?

A. Are the machines in a Windows NT domain, thus actually using the SAME account? Or are they stand-alone machines running Windows NT Workstation, thus using accounts with the same *name* but actually different accounts (since the security authorities are different)? Recall that each machine running Windows NT Workstation is a security authority, and an account MarkR on machine1 (machine1\MarkR) is a different account than account MarkR on machine 2 (machine2\MarkR)). These issues are covered in additional detail in question 4, titled "I get E_ACCESSDENIED from CoCreateInstanceEx. Why?"

Also, is the NTFS access local to the machine where the server is running or is it remote? All remote filesystem accesses fail for any localservers launched as Launching User (with the exception of those launched from within the interactive account) fail.

The "run as Launching User" feature of DCOM is quite limited and should be avoided in most cases. The Launching User mode requires that DCOM impersonate the caller before starting the localserver; the resulting process is somewhat crippled from a security perspective--it doesn't have a full security token of the caller.

These limitations have to do with NT security limitations as discussed above question 7, "Does DCOM Support Delegation Level Impersonation?"

These limitations (both with security and with how DCOM is affected) will be removed, or at least greatly improved, in Windows NT 5.0.

Q11. Should I use AccessCheck or IsValidSecurityDescriptor?

A. AccessCheck actually checks for valid access rights. IsValidSecurityDescriptor simply verifies that the structure is properly formed.

Q12. How can I get a log of AccessCheck failures?

A. The Debug version of Ole32.dll (included in the checked build of Windows NT) prints messages to the debugger when AccessCheck calls fail. Future versions of DCOM will support auditing.

Q13. How can I troubleshoot activation problems?

A. If you have a sound card in your computer, enable the "process start" and "process stop" sounds. If you hear the process start sound when you do an activation, but you still get an error (like E_ACCESSDENIED), you know that activation worked and your problem is related to call-level security. Remember that launch permissions should always be more restrictive than access permissions. Look in the event log on the client and server machines.

Q14. Why do I get a "User32.dll could not be initialized" message?

A. An application without permissions tried to access the desktop.

Q15. Why do I get a "Shell32.dll could not be initialized" message?

A. The user did not log into the machine, but an application attempted to access the user's profile. This is because some API calls require the running user's profile to be present on the machine. The profile is not created until you log in.

Q16. How can I troubleshoot call-level problems?

A. If activation works, but calls fail, consider the following:

  • The authentication level is negotiated. If you have a Windows 95 client with authentication level connect and a Windows NT server with authentication level encrypt, DCOM tries to use encrypt for calls in both directions. Since Windows 95 cannot receive calls at encrypt, the NT machine cannot call the Windows 95 machine. Thus both the client and server have to set the authentication level to the lowest value allowable for any call in any direction.

    Similarly if you have two processes, one with a login token and the other with an impersonation token and you set the authentication level to none in the second, it still won't be able to call the first if its authentication level is not none.

  • Did the call reach the server? (Use a debugger to find out.) If the call reached the server, the error may have been returned from the server, rather then DCOM.
  • Did COM return an error or did the server return an error? If the server returned an error, step through the server function to debug it. If COM returned an error because of security, then Ole32.dll prints a message to help you debug it. COM may have returned an error because the client machine couldn't reach the server or the domain controller.
  • If it's the apartment model, is the server dispatching messages? This is the most common problem. Apartment model servers require a message pump. If the server doesn't dispatch messages, no calls succeed.
  • If the server is not run as interactive user, does it hang displaying a pop-up on a hidden desktop? This is the most common instance of the previous problem. If the server is not running on the desktop and it displays a pop-up, the application appears to hang mysteriously. Break in with the debugger and get a stack trace. Print the parameters to the dialog box APIs to see what the pop-up is for.
  • NTLMSSP prevents RunAs the Launching User from making secure network calls. See question 10, "What are the Limitations of RunAs the Launching User?" NTLMSSP is the security provider package that provides Windows NT security.

  • Default access permissions are not obvious. For legacy applications, if there is no AccessPermission value under the APPID and no DefaultAccessPermission value, COM creates a security descriptor. COM finds the SID of the process token and constructs a security descriptor or IAccessControl allowing that SID and local system. Thus if you run Excel and Word from the command prompt, they can talk to each other. However they cannot talk to a process on the same machine running as someone else.

Q17. Are there any hints on impersonation problems?

A. Consider the following:

  • Make sure the owner and group are set in all security descriptors. AccessCheck fails if the owner and group are not set.
  • Grant access to the SYSTEM account. Rundowns and other activation calls (lazy use protseq) fail if system does not have permission.
  • Impersonation nested in the apartment model. If a process receives a call, impersonates the client, and receives another call on the same thread, the new call begins with no thread token. When the new call completes, COM restores the previous call's impersonation token.
  • NTLMSSP in Windows NT 4.0 does not allow delegation-level impersonation. If you set the impersonation level to delegation or anonymous on Windows NT 4.0 with NTLMSSP, CoInitializeSecurity succeeds and all your calls fail.

Q18. Why does CoCreateInstance fail in my ISAPI extension?

A. A COM server that is an EXE must include the IUSR_computername Internet guest account in its launch and access security permissions before it can be launched by an ISAPI extension DLL. In addition, if the server is an EXE server that is not a Win32 service, it must be configured to run under a specific user account using the RunAs registry value. See http://www.microsoft.com/kb/developr/ole/q156223.htm for more details.

COM Security on Windows 95

This section discusses COM security issues relating to the DCOM enabled version of COM for Windows 95.

Q19. Where can I get DCOM for Windows 95?

A. You can get DCOM for Windows 95 by downloading it from the COM/OLE developer site on www.microsoft.com. The URL is http://www.microsoft.com/oledev/.

Q20. Can I redistribute DCOM for Windows 95?

A. Once the release version of DCOM for Windows 95 is available, you can redistribute a self-installing .exe file that updates the end users system with DCOM for Windows 95 and have your application's setup program spawn it.

Full details of how you should to this, including redistribution terms, are documented in the EULA agreement contained within the self- extracting .exe file.

Q21. What Security Features are in COM on Windows 95?

A. Prior to the release of the DCOM enabled version of COM for Windows 95 there were no security issues related to COM on Windows 95; COM on Windows 95 had no security. The DCOM enabled version of COM for Windows 95 includes a sub-set of the COM security found on Windows NT. The following items detail what is supported and what is not:

  • Call-level security

    CoInitalizeSecurity, IClientSecurity, CoGetCallContext, IServerSecurity, and the related helper APIs are all fully supported.

    Windows 95 machines can make calls at any authentication level, but incoming calls never arrive with a higher authentication level than connect (RPC_C_AUTHN_LEVEL_NONE or RPC_C_AUTHN_LEVEL_CONNECT).

    Note that the first beta of DCOM for Windows 95 does not support external configuration of access permissions in the registry; all processes that do not call CoInitializeSecurity on this release will be completely insecure.

  • Remote connections

    By default DCOM for Windows 95 does not allow remote machines to connect to running objects. The HKEY_LOCAL_MACHINE\Software\Microsoft\OLE registry key has as a named value "EnableRemoteConnect." By default this value is set to "N." To enable remote connections, change this value to "Y." You can do this in the OLE/COM Object Viewer with the File.System Configuration dialog box. Changing this value requires a reboot.

    If EnableRemoteConnect is not set to "Y," then all incoming calls are rejected (the caller, typically, gets an RPC_S_SERVER_UNAVAILABLE return code). Remote calls from the machine work (assuming DCOM is enabled).

  • Activation

    All processes on Windows 95 run under the same security blanket: that of the currently logged on user. Thus it is not possible to securely launch process from another machine. DCOM on Windows 95, therefore, does not support remote activation. Processes have to be started either manually, or via some other mechanism. For example, running a COM server with the /Embedding command line switch causes the server to register its class factory objects (via CoRegisterClassObject); remote machines can then successfully connect to the running instance (for example, by calling CoCreateInstanceEx).

    The DefaultLaunchPermissions and LaunchPermissions registry values have no effect on Windows 95.

Windows NT Security Issues

The COM Security architecture leverages the design and ideas of the Windows NT security architecture.

Q22. Where can I find more information on Windows NT Security?

A. See the References section of this article.

REFERENCES

For more information, please see the following article in the Microsoft Knowledge Base:

      ARTICLE-ID: Q156673
      TITLE     : Helsvc.exe Implements an OLE Server in a Service

      ARTICLE-ID: Q156223
      TITLE     : How To Launch OLE Servers from ISAPI Extensions

Win32 Programmers Reference; search on Overview, System Services, and Security

MSDN Security API series; search on Windows NT Security in Theory and Practice, The Guts of Security, Security Bits and Pieces, and A Homegrown RPC Mechanism


Additional query words: FAQ COM DCOM
Keywords : OleTwoCom kbfaq
Technology : kbMfc kbole kbAtl kbInetDev
Version : 4.0
Platform : WINDOWS


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: December 10, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.