MORE INFORMATION
Table of Contents
General COM Security Issues
- How do I enable or disable DCOM?
- Why do I receive E_OUTOFMEMORY when trying to access a remote object?
- Why does IConnectionPoint::Advise not work?
- I receive E_ACCESSDENIED from CoCreateInstanceEx. Why?
- Are there any issues with running COM servers under the "system"
account?
- Why does CoRegisterClassObject return CO_E_WRONG_SERVER_IDENTITY?
- Does DCOM support delegate level impersonation?
- LocalServer32 entries with UNC names cannot be remotely activated. Why?
- Why can I not access network resources with my server?
- What are the limitations of RunAs the Launching User?
- Should I use AccessCheck or IsValidSecurityDescriptor?
- How can I receive a log of AccessCheck failures?
- How can I troubleshoot activation problems?
- Why do I receive a "User32.dll cannot be initialized" error message?
- Why do I receive a "Shell32.dll cannot be initialized" error message?
- How can I troubleshoot call-level problems?
- Are there any hints on impersonation problems?
- Why does CoCreateInstance fail in my ISAPI extension?
COM Security on Windows 95
- Where can I download DCOM for Windows 95?
- Can I redistribute DCOM for Windows 95?
- What security features are in COM on Windows 95?
Windows NT Security Issues
- Where can I find more information about 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 you to restart your computer.
If EnableDCOM is not set to "Y," then all cross-computer calls are rejected
(the caller, typically, receives 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 computer, 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 restart.
Q2 Why do I receive 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, instead of E_ACCESSDENIED, because of a bug in
Windows NT 4.0. This will be fixed in future releases of DCOM.
This failure may occur both when trying to activate an object (through
CoCreateInstanceEx, for example) and when receiving a pointer to a remote
object (in the implementation of IConnectionPoint::Advise, for example).
See the question that follows, "Why does IConnectionPoint::Advise not 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:
Q3 Why does IConnectionPoint::Advise not work?
A. For IConnectionPoint::Advise (or for any other interface method
that passes an IUnknown pointer) to work correctly, it must have the
appropriate access permissions to the object to call
QueryInterface on any remote interface.
You are probably not calling CoInitializeSecurity() in your client and are
therefore picking up the default DCOM-supplied security blanket. The client
application must initialize security so that the server process
identity is permitted to call in 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 to the
client is 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
computer.
Because you are writing a real DCOM application, you must 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 essentially allow anyone to call to the client
process. If the server hands a reference to your sink to someone in a different location and he tries to call back, he will get in just fine. See information about 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 must 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 receive E_ACCESSDENIED from CoCreateInstanceEx. Why? I am an
administrator on my computer and on the second computer.
A. Windows NT security principles 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 computer that runs Windows NT
Workstation is a member of a domain (all computers running Windows NT Server
are members of a domain by definition). Even when in a Windows NT Server
domain, computers running Windows NT Workstation continue to be their own
security authorities with (potentially) local-only accounts. However, they
"trust" (can pass along security requests to) the domain
controls of the domain where they reside.
For example, on a domain named "Test," my security identity would be
"Test\MarkRy," even if I am logged on to my computer "Markry_Tecra." But if
my computer is a standalone computer (or if I log on locally), my identity
would be "Markry_Tecra\MarkRy." This is a completely different security
principle. You may think of computers running Windows NT Workstation as
domains of one. They either trust another Windows NT (real) domain and
then refer security-related decisions about principles 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 as though you have two standalone computers running
Windows NT Workstation and, therefore, two completely different security
principles. You log on to one as Computer1\RJF, and the other as
Computer2\RJF. The fact that your account on each is an admin account does
not matter because they are different accounts.
However, you can have two computers running Windows NT Workstation that
are not in the same or trusting domains (and, therefore, cannot have the
same principle logged on to both at the same time) to interact with enhanced security because Windows NT Workstation falls back to a "matching account names and
passwords" mode. If you use the same ASCII names on the two computers
running Windows NT Workstation and the accounts have the same passwords,
then DCOM and other NT security (such as filesystem) must work as though
you were really logged on to the two computers 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. I cannot use my Test\MarkRy account
on Computer1 and a Computer2\MarkRy account on the other computer
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 tries by a different MarkRy that comes from an
distrusted domain (or computer 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 computer running Windows NT Server from a
Windows NT Workstation user, but the Windows NT Workstation computer
itself is not part of the same domain (or of a trusted domain), you
must create a special kind of user account named 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
computer 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. Local accounts are never delegated for security
checks, so they cannot be used in trusted domains. 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
computers 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 privileged account locally, so you must not run
any shareware applications there. However, it has no network credentials and
cannot leave the computer through any security-enhanced Windows NT mechanism, including file
system, named pipes, DCOM, or security-enhanced RPC.
Q6 Why does CoRegisterClassObject return CO_E_WRONG_SERVER_IDENTITY? When
launching my ATL 1.1 server service as an .exe file, I receive
CO_E_WRONG_SERVER_IDENTITY from CoRegisterClassObject. (The class is
configured to run as a security ID different from the caller.) This seems
to occur whether I skip the CoInitializeSecurity or not. 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 identity. Because 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, follow these 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"
You muist 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 put a UNC in the LocalServer32 entry of a DCOM object, that object
may no longer be launched from a remote computer. Is there a security patch or
workaround other than the following one? DCOM tries to
access the LocalServer32 executable from the System account (null session).
If you configure the computer where the executable is located to permit
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 computer restart to take effect. This
is apparently a bug in DCOM. DCOM uses the RunAs key to
determine how to access the server executable and impersonate that user
before trying any access.
A. It is not a bug in DCOM. Try it yourself: impersonate a user coming from
a remote computer and then try any network-related operation that uses NT
security. It does not work. If it did work, impersonation can form an
endless chain. Allowing threads to impersonate you would be much more
risky, as the threads may then open your e-mail folder on a remote
computer, and may also change your password on the domain controllers.
Windows NT 5.0 supports full security delegation (what it
would take to make chaining scenarios work) but only when several 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 several minutes or whatever you set). The
other safeguard would be an extension to the ACL model that would permit you
to distinguish between the "real" you and your delegates.
Q9 Why can my server not 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 through a method call, ITest::Do().
When I deploy my server on Windows NT 4.0 Workstation and use the default
security of Launching User, file access does not work when I call my method
ITest:Do() remotely. It fails with an access permission.
I would expect identity "Launching User" if I had an administrator user on
computer A and the same administrator user on computer B. Then the identity
of my launched server would be that administrator user on computer B.
However, it drops some rights because my file access fails. When I set the
identity to RunAs with the administrator user on computer B, everything
works. What is the difference?
A. Are the computers in a Windows NT domain using the SAME
account? Or are they stand-alone computers running Windows NT Workstation,
therefore using accounts with the same *name* but actually different accounts
(because the security authorities are different)? Recall that each computer
running Windows NT Workstation is a security authority, and an account
MarkR on computer1 (computer1\MarkR) is a different account than account
MarkR on computer 2 (computer2\MarkR)). These issues are covered in
additional detail in question 4, titled "I receive E_ACCESSDENIED from
CoCreateInstanceEx. Why?"
Also, is the NTFS file system access local to the computer where the server is running
or is it remote? All remote filesystem accesses fail for any localservers
launched as Launching User (except for those launched from
in the interactive account) fail.
The "run as Launching User" feature of DCOM is quite limited and must typically be
avoided. The Launching User mode requires that DCOM
impersonate the caller before starting the localserver. The process that results does not have a
full security token of the caller.
These limitations have to do with NT security limitations as discussed
in 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 verifies that the structure is correctly
formed.
Q12 How can I receive 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 receive an error (like E_ACCESSDENIED), you know
that activation worked and your problem is related to call-level security.
Remember that start permissions must always be more restrictive than
access permissions. Look in the event log on the client and server
computers.
Q14 Why do I receive a "User32.dll cannot be initialized" error message?
A. An application without permissions tried to access the desktop.
Q15 Why do I receive a "Shell32.dll cannot be initialized" error message?
A. The user did not log on to the computer, but an application tried to
access the user profile. Some API calls require the
running user profile to be present on the computer. The profile is not
created until you log on.
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. Because Windows 95 cannot receive calls at encrypt,
the NT computer cannot call the Windows 95 computer. Both the
client and server have to set the authentication level to the lowest
value permitted for any call in any direction.
Similarly if you have two processes, one with a logon token and the
other with an impersonation token and you set the authentication
level to none in the second, it still cannot 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 an error message to help you debug it. COM may have returned an error
because the client computer cannot reach the server or the domain
controller.
- If it is the apartment model, is the server dispatching messages? This
is the most common problem. Apartment model servers require a message
pump. If the server does not dispatch messages, no calls succeed.
- If the server is not run as interactive user, does it stop responding displaying
a pop-up menu 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 menu, the application appears to not respond.
Break in with the debugger and get a stack trace. Print the
parameters to the dialog box APIs to see what the pop-up menu is for.
- NTLMSSP prevents RunAs the Launching User from making security-enhanced 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 do not appear. 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. Therefore,
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 computer
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 permit 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 start and access security permissions before it can
be launched by an ISAPI extension DLL. Additionally, 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.
For additional information, click the following article number to view the article in the Microsoft Knowledge Base:
156223
HOWTO: Launching OLE servers from ISAPI extensions
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 download DCOM for Windows 95?
A. You can download DCOM for Windows 95 from the COM/OLE
developer site. For more information, visit the following Microsoft Developer Network (MSDN) Web site:
Q20 May I redistribute DCOM for Windows 95?
A. When 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 must do this, including redistribution terms, are
documented in the EULA agreement contained in the self-extracting .exe
file.
Q21 What Security Features are in COM on Windows 95?
A. There were no security-enhancement issues related to COM on Windows 95 before the release of the DCOM-enabled version of COM for Windows. COM on Windows
95 had no security. The DCOM-enabled version of COM for Windows 95 includes
a subset of the COM security that you find 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 computers may make calls at any authentication level, but
incoming calls never arrive with a more rigorous authentication level than
connect (RPC_C_AUTHN_LEVEL_NONE or RPC_C_AUTHN_LEVEL_CONNECT).
Note 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 lack security.
- Remote connections:
By default, DCOM for Windows 95 does not permit remote computers 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 may do this
in the OLE/COM Object Viewer with the File.System Configuration
dialog box. Changing this value requires a restart.
If EnableRemoteConnect is not set to "Y," then all incoming calls are
rejected (typically, the callerreceives an RPC_S_SERVER_UNAVAILABLE
return code). Remote calls from the computer work (assuming that you enable DCOM).
- Activation:
All processes on Windows 95 run under the same security blanket: that
of the currently logged on user. You cannot securely
start a process from another computer. Therefore, DCOM on Windows 95
does not support remote activation. You must manually start processes, or start them through some other mechanism. Running a
COM server with the /Embedding command line switch causes the server
to register its class factory objects (through CoRegisterClassObject).
Remote computers can then successfully connect to the running instance
(for example, when you call CoCreateInstanceEx).
The DefaultLaunchPermissions and LaunchPermissions registry values
do not affect 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 about Windows NT Security?
A. See the References section of this article.