![]() |
Show Changes |
![]() |
Edit |
![]() |
|
![]() |
Recent Changes |
![]() |
Subscriptions |
![]() |
Lost and Found |
![]() |
Find References |
![]() |
Rename |
| Search |
History
| 5/31/2008 3:31:58 PM |
| PSWEB-keith |
| 9/18/2006 7:48:05 PM |
| -65.57.245.11 |
| 8/1/2006 3:20:00 AM |
| -203.199.198.152 |
| 11/23/2004 2:13:46 PM |
| KimGräsman-217.21... |
| 11/23/2004 2:11:42 PM |
| -217.215.12.69 |
![]() |
List all versions |
Last Update: 3 May 2000
Thanks to everyone on the DCOM list who have helped to ferret out all the subtle gotchas regarding COM security. This FAQ is an attempt to reduce the workload of these fantastic folks by answering many commonly asked questions. Feel free to edit this FAQ.
- Keith Brown, Pluralsight LLC, http://www.pluralsight.com/keith
Much of what this document covers also applies to Win9X. However, this document is targeted at the Windows NT family of OS's.
I was just curious tonight (21 Oct 99), so I did a search for "security and problem" in the DCOM list archives and got 2200 hits. You're not alone!
Q: Isn't there already a COM Security FAQ at Microsoft?
A: Yes there is (http://support.microsoft.com/kb/q158508/) Consider this as a complement to the existing work by Charlie Kindel. This FAQ attempts to address more recent inquiries on the list, and hey, Charlie is a busy guy ![]()
x
Q: I just want to turn off all security for my DCOM app. How can I do this?
A:
Here's how an activation call is processed:
If you don't care about security and want to make your activation calls fast (potentially avoiding the latency of waiting for authentication to fail multiple times), then use this function instead of CoCreateInstanceEx:
HRESULT FastCoCreateInstanceEx(REFCLSID clsid, const OLECHAR* pszHostName,
ULONG cMQI, MULTI_QI* rgmqi )
{
COAUTHINFO cai = { RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, 0,
RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE,
0, EOAC_NONE };
COSERVERINFO csi = { 0, const_cast<OLECHAR*>(pszHostName), &cai, 0 };
return CoCreateInstanceEx( clsid, 0,
CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER, &csi,
cMQI, rgmqi );
}
Q: Is there a book I can read to help me master COM security?
A: This is a shameless plug, but if you like this faq, and you like the advice I normally give on the DCOM list, you'll probably like the book I've written on security (for programmers). Its title is Programming Windows Security, and it was published on June 30, 2000 by Addison Wesley.
Q: What should I do before I post a security related question to the DCOM list?
A: Be sure to turn on auditing of logon/logoff events (both success and failure) on all your test machines that support auditing (servers AND clients) (Win9X doesn't support this).
Include in your post any interesting information you find in the security and System event log (especially with CO_E_SERVER_EXEC_FAILED, the event log is tremendously helpful).
It's kind of late and I'm tired, so if anybody else comes up with a suggestion for standard stuff that folks should include in their posts, please email me a brief message and I'll incorporate your feedback.
Q: Does DCOM work with firewalls or proxies?
A: A fellow went to the doctor. He said, "Doc, it hurts when I slam my head against the wall." The doctor replied, "Don't do that."
If this parable doesn't satisfy you, Mike Nelson has a paper on this subject.
Note that DCOM is not the only way (certainly not even a particularly good way) to communicate across the Internet. Have you considered using straight HTTP (perhaps in concert with ASP)?
SOAP is also another emerging alternative. See http://www.develop.com/soap/soapfaq.htm for more details on SOAP.
Q: Can I control (programmatically) the security environment of a VB component?
A: Yes, but it's a bit harder. You cannot call CoInitializeSecurity in a Visual Basic component (even when it's packaged as an EXE), because by the time your code is loaded into the VB runtime, this function has already been called using the default settings in the registry. Therefore you must use registry settings under your AppID to control your security settings. NT4 SP4 and greater allows the authentication level to be specified on a per-application basis via a named value under the application's AppID. This is often the most important setting, especially if you simply want to turn off COM security for your application.
In order to keep your customers from having to grunge around in DCOMCNFG to get your application working reliably, consider adding some code to your install script that adjusts the security settings for your AppID. Look at the Platform SDK documentation (search for "AppID Key") to find the details of which named values refer to which security attributes. Do not be tempted to adjust machine-wide security settings though, as you are guaranteed to silently break at least one other fellow VB application.
Another option is to package your code in a DLL, and have a simple C++ EXE load your component, after calling CoInitializeSecurity. If you don't like these hacks, send your comments to mswish@microsoft.com and maybe the VB team will cave in and acknowledge that support for programmatic security is in fact an important feature.
Q: I'm getting E_OUTOFMEMORY errors when I unmarshal an interface pointer.
A: Make sure the SYSTEM account is granted access permissions in the server process, either by calling CoInitializeSecurity, or via DCOMCNFG (if you are not explicitly calling CoInitializeSecurity).
COM does not have any specific requirement that the SYSTEM account be granted launch permissions, BTW.
Q: COM is launching multiple copies of my server process, even though I am registering my class objects with REGCLS_MULTIPLEUSE.
A: Configure your server to RunAs a distinguished user. You can do this via the DCOMCNFG identity tab. This is the recommended setting for release builds (i.e., when you ship the code). When running debug builds, it is highly advisable to use "Interactive User". In this case, someone will need to be logged into the server interactively. This will allow you to see any ASSERT dialogs that pop up, among other added benefits. You generally should avoid the "Launching User" setting (the default) for distributed applications.
Note that whatever user account you choose should have the "Logon as a Batch Job" right.
Q: I have chosen to run my server as a distinguished user. Do I really need to grant this user the "Logon as a Batch Job" right, and if so, how can I do this?
A: Whenever you choose to run a server as a distinguished user, you must grant that user account the "Logon as a Batch Job" right via User Manager. This must be granted on the machine where the server runs. This is not optional! The reason for this is that before launching the server process, the SCM calls the LogonUser API using a batch-type login, and this will only work if the user being logged in is granted this right. This failure is one of the causes of the dreaded Server Execution Failed error.
Note that privileges are assigned on a per-machine basis, so you must set this privilege either interactively via User Manager or programmatically via the LSAAPI (see my Nov '98 MSJ column and errata page :-/) on the machine where the server runs. NT4 backup domain controllers are the exception: in this case you must always set the privilege on the PDC, where it will be replicated to the BDCs in the domain.
DCOMCNFG normally grants this right when you choose to run as "This User". This is one of the reasons why DCOMCNFG must be run by someone in the local Administrators group, since an administrator is required to grant privileges to user accounts. In NT4SP3, DCOMCNFG fails to assign this right if your server runs on a BDC, because it doesn't explicitly watch for this case and contact the PDC instead.
Q: I am impersonating the client during a COM call, and I am getting Access Denied when I try to access local files that the client has explicitly been granted access to.
A: Be sure the client has granted you RPC_C_IMP_LEVEL_IMPERSONATE level of trust. This can be done on a proxy by proxy basis via IClientSecurity::SetBlanket, or can be set as a default for the entire client application via CoInitializeSecurity. If you don't do either of these things, the default setting in the registry is a machine-wide setting that defaults to RPC_C_IMP_LEVEL_IDENTIFY, which will allow CoImpersonateClient calls to succeed, but will inhibit you from opening any executive objects while running as the client.
Q: My client calls AtlAdvise on a remote object, and it fails with E_ACCESSDENIED.
A: The object you are connecting to is attempting to make a callback (QueryInterface), but is failing with E_ACCESSDENIED, and is propagating the result back to you.
If the principals in question are members of different domains:
Unless the client's domain (e.g., if the client's account is FOO\Bar, this is FOO) trusts the domain where the object runs (e.g., if the object's machine is set to run in the QUUX domain, this is QUUX) callbacks from the object to the client cannot be authenticated.
Either add a trust relationship between the domains (so FOO trusts QUUX), or turn off authentication if your client doesn't mind anonymous callbacks.
If you don't mind anonymous callbacks:
To turn off authentication for callbacks, the client must call CoInitializeSecurity passing RPC_C_AUTHN_LEVEL_NONE, and the server must explicitly crank down authentication on the proxy before making any callbacks (including QueryInterface) by calling SetBlanket (on the IUnknown pointer for QueryInterface, and on the callback interface for the interesting methods), setting the authn level to RPC_C_AUTHN_LEVEL_NONE. This must be done before making the call to QueryInterface, so you'll have to hook into the ATL connection point implementation (this is beyond the scope of this FAQ, so use the source, Luke).
If you want callbacks to be authenticated, and not anonymous:
The client will need to grant the server access permissions, via DCOMCNFG, or even better, via CoInitializeSecurity.
Q: "A Security Package Specific Error has Occurred (0x80070721)" - what the heck?
A: This error is most commonly encountered when you try to make an outgoing remote COM call (typically a callback, this often occurs when calling AtlAdvise) from a COM server that is set to run as the Launching User. RunAs a distinguished user instead. The problem you are encountering is that your process does not have network credentials to make the remote COM call.
Another common cause of this error is if you attempt to make an outgoing COM call from a process that runs in the SYSTEM logon session. The SYSTEM logon session has no network credentials (this is fixed with Kerb in Win 2000, BTW), so you must either turn off authentication, or explicitly provide credentials via SetBlanket for proxies, and COSERVERINFO for activation requests, by filling out a COAUTHIDENTITY structure.
Q: I call CoInitializeSecurity from my inproc server, and I get RPC_E_TOO_LATE.
A: CoInitializeSecurity can only be called once per process. If your client process doesn't call it, then COM automatically calls it (using settings in the registry) when the first interesting event occurs. So the net result is that by the time your object is created, CoIS has already been called. You cannot control your security environment as an inproc server. If you need this control, consider packaging your object in an out-of-proc server instead, or use a surrogate process.
For those of you writing code to be hosted in a surrogate (perhaps DLLHOST or MTS), you'll need to specify your security settings declaratively:
Q: After calling CoImpersonateClient in my COM server, when I make calls to another COM server, the proxy seems to ignore the fact that I am impersonating.
A: This is by design. COM proxies ignore impersonation tokens and always use the process token by default. However, by calling IClientSecurity::SetBlanket, you can choose alternate credentials via a COAUTHIDENTITY structure. Note that if you pass a NULL pointer for this structure when calling SetBlanket, if you are impersonating, COM will cache the impersonation token and use it instead of the process token (this feature, which appears to have always existed in SP3, was documented around the time that VC6 shipped).
Note that SetBlanket has no effect on proxies to local (same host) objects, except for the impersonation level, which can be adjusted dynamically (in this case, IServerSecurity::QueryBlanket always returns RPC_C_IMP_LEVEL_ANONYMOUS, at least in SP4, but the token you get from CoImpersonateClient does have the correct impersonation level).
Q: I usually use DCOMCNFG to control my EXE server's custom access control policy, but lately it seems like changes I make in DCOMCNFG are not taking effect.
A: A number of things could be happening:
If you use ATL, go update the name of your binary in your application's main RGS script (where the AppID is defined). Note that even if you do call CoInitializeSecurity, this mapping is still used by COM in some esoteric scenarios e.g., when you call IRunningObjectTable::Register(ROTFLAGS_ALLOWANYCLIENT,...) to look up your RunAs setting to counter spoofing. So you still need this mapping to be correct. Sad but true.
3. Your EXE to AppID mapping is missing altogether (see the previous point).
4. You have an ATL-based LocalServer with a long filename. Check your LocalServer32 entry to make sure it doesn't use the short filename syntax, (i.e., "MYWOND~1.EXE" instead of "MYWONDERFULSERVER.EXE"). The ATL wizard sets up your server's RGS script to use the long filename for the AppID --> EXE mapping, but if your server was launched by the SCM using the short form of the name, the module name will show up as a short name (you can see this in taskmgr's process list), and COM won't be able to find your If your really want to avoid this particular problem during development, one approach is to simply avoid using a long filename for your server, or heaven forbid, call CoInitializeSecurity so you can programmatically control your access control policy.
If you really feel strongly about storing your security configuration (authn level, access permissions, imp level) in the registry, don't rely on an EXE-->AppID mapping to tell COM what your AppID is. Just call CoInitializeSecurity and be explicit. Here's a simple example (if only the ATL wizard would generate this code, life would be sooo much easier):
void main() {
CoInitializeEx(0,0); // or whatever
// replace this string with your AppID
struct __declspec(uuid("12341234-1342-1234-1234-123412341234")) lazyMansGuidDefinition;
GUID MyAppID = __uuidof(lazyMansGuidDefinition);
CoInitializeSecurity(&MyAppID, 0, 0, 0, 0, 0, 0, EOAC_APPID, 0);
// ...
}
This code tells COM exactly what your AppID is, and asks COM to load the declarative settings from the registry. If you really want to use an AppID to configure your application's security settings, this is the safest way to do it.
Q: I'm getting CO_E_SERVER_EXEC_FAILURE (0x80080005) when I try to create an instance of a COM object on a remote server. What's up?
A: The SCM is attempting to launch the server and is failing for some reason. The SCM takes two steps to get this done:
If you have chosen to run your server as a distinguished principal, the SCM obtains a token by calling LogonUser. This is often the step that fails and causes the error you are seeing. Here are some reasons why LogonUser might fail:
When diagnosing this error, you might consider the following steps:
Q: I've been looking at the COM spec's chapter on security, and wow, it really doesn't seem to match the SDK documentation. What's up with that?
A: While some of the ideas are still applicable (not all), the COM spec is woefully out of date with respect to the current implementation. Things like per-class activation security (which doesn't exist) are discussed there, the interface descriptions of IClientSecurity don't match, calls like CoRegisterAuthenticationService are discussed, but don't exist. Avoid chapter 8 of the COM spec.
The most detailed reference is "Programming Windows Security": http://www.pluralsight.com/books/pws/ with a more accessible but less detailed version in my latest book .
This is KeithBrown's wiki. Visit the HomePage for more info. If you have any feedback, please contact Keith .
About FlexWiki.
Recent Topics