如何在DCOM中的模拟工作? [英] How does impersonation in DCOM work?

查看:162
本文介绍了如何在DCOM中的模拟工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用OLE自动化编组器的DCOM客户端和服务器应用程序。当在同一台电脑上运行时,它们工作正常,但是当服务器在不同的PC上不在同一个域中时,我得到E_ACCESSDENIED(0x80070005)。



dcomcnfg将所有对DCOM对象的访问权限授予在客户端上指定其登录名和密码的用户。 ServerApp及其类型库在服务器PC上注册。



类型库也在客户端PC上注册。我直接在ClientApp中指定服务器名称,所以根据我的理解,客户端PC上不需要dcomcnfg配置。



CreateInstanceEx()与服务器名称,登录,域和密码工作正常。它返回IUnknown,同时在服务器PC上启动ServerApp。



但是当我尝试QueryInterface()为服务器支持的接口,我得到E_ACCESSDENIED。 p>

分析安全事件日志,我有两个记录:



首先,用户成功登录网络凭证在ClientApp中指定。当我调用CreateInstanceEx()时,会发生这种情况。



接下来,我在客户端PC上登录的用户< >。因为两个PC不在一个域中,所以这个用户对于服务器PC是未知的。



现在,为什么这个用户会登录服务器,特别是当我调用QueryInterface的所有东西?



学习CreateInterfaceEx params,它似乎有某种模拟机制。但不清楚谁模仿谁。有三个用户凭据:


  1. ServerApp在服务器PC上运行的用户(在dcomcnfg中配置)


  2. PC。


无论你怎么看,如果#3涉及到一个用户太多。如果DCOM要在服务器PC上识别/假冒#3,为什么我需要指定#2的凭据?到什么时候?



DCOM仿冒逻辑来模拟#2,因为这是我明确指定为我的凭据。但是为什么第二次登录尝试呢?



有人可以解释模拟的工作原理,以及如果有办法忽略它并以dcomcnfg中指定的用户身份运行

解决方案

回答自己的问题。经过大量探索,很明显, DCOM有两种不同的识别情况


  1. 对象创建的授权(CoCreateInstanceEx)

  2. 方法调用的授权。

由于未知原因,#2不会继承# 1设置。默认情况下,它使用客户端进程的凭据,因此会产生奇怪的登录。



有两种方法可以指定#2的凭据。第一个是 CoSetProxyBlanket 。它仅设置指定代理(marshaller-unmarshaller)的凭据:

  CoCreateInstanceEx(IID_IObject1,/ * login,pass * obj1); //成功! 
//登录并接收obj1中的IObject1代理

obj1-> DoSomething();
// obj1中的IObject1代理现在尝试在进程凭据下登录。
//失败! E_ACCESSDENIED

CoSetProxyBlanket(obj1,/ * login,pass * /); //成功!
//现在授权IObject1代理。

obj1-> DoSomething(); //成功!
obj1-> QueryInterface(IID_IObject2,obj2); //成功!

obj2-> DoSomethingElse(); //失败!
//这个不同的IObject2代理还没有被授权。

CoSetProxyBlanket(obj2,/ * login,pass * /);
//等。需要注意的是,虽然CoCreateInstanceEx需要模拟级别至少为IMPERSONATE,但CoSetProxyBlanket似乎并不支持



另一个选项是使用 CoInitializeSecurity 可为整个过程设置默认凭据。然后你不必在每个代理上调用CoSetProxyBlanket:

  CoInitializeSecurity(/ * login,pass * /); 
CoCreateInstanceEx(IID_IUnknown,/ * login,pass * /,obj); //成功!
obj-> DoSomething(); //成功!

在客户端上使用CoInitializeSecurity时,还必须指定 asAuthSvc 虽然MSDN说你不。



这个方法的缺点显然是,如果你有几个DCOM对象从不同的PC,你将不得不指定所有



当你从一个不同的代理运行时,它也是不可靠的。 DLL(如果一个进程有不同的默认安全?)。因此,最好在每次调用返回之前实现CoSetsProxyBlanket的QueryInterface包装。


I have a DCOM client and server applications which use OLE automation marshaller. They work fine when run on the same PC but when the server is on a different PC not in the same domain I get E_ACCESSDENIED (0x80070005).

Server PC is configured with dcomcnfg to give all access to any DCOM object to the user whose login and password I specify on the client. ServerApp and its type library are registered on the server pc.

Type library is also registered on the client PC. I specify server name directly in the ClientApp so no dcomcnfg configuration is needed on the Client PC as far as I understand.

CreateInstanceEx() with server name, login, domain and password works fine. It returns IUnknown and at the same time starts ServerApp on server PC.

But when I try to QueryInterface() for the interface which server supports, I get E_ACCESSDENIED.

Analyzing the Security Event Log, I have two records there:

First, a successful network login by the user whose credentials I specify in ClientApp. This happens when I call CreateInstanceEx().

Next, a failed login attempt by the user under which I'm logged in on a client PC. Since two PCs are not in a domain, this user is unknown to server PC.

Now, why the heck would THIS user be logging into server, especially when I call QueryInterface of all things?

Studying CreateInterfaceEx params, it appears there's some kind of impersonation mechanism going on. But it's unclear who impersonates who. There are THREE user credentials involved:

  1. User under which ServerApp runs on the server PC (as configured in dcomcnfg).

  2. User whose credentials ClientApp specifies when connecting.

  3. User under whose credentials ClientApp runs on client PC.

No matter how you look at it, if #3 is involved it's one user too much. If DCOM is going to identify/impersonate #3 on server PC anyway, why do I need to specify #2's credentials? To what point?

It would have seem logical for DCOM to impersonate #2 because this is what I have explicitly specified as my credentials. But why the second login attempt then?

Can someone please explain how exactly the impersonation works, and also if there's a way to just ignore it and run as user which is specified in dcomcnfg?

解决方案

Answering my own question. After much exploration it became apparent that DCOM has TWO different identification cases:

  1. Authorization for object creation (CoCreateInstanceEx)
  2. Authorization for method calls.

For reasons unknown, #2 doesn't inherit #1 settings. By default it uses the credentials of the client process, hence strange logins.

There are two ways to specify credentials for #2. First one is CoSetProxyBlanket. It sets credentials for a specified proxy (marshaller-unmarshaller) only:

CoCreateInstanceEx(IID_IObject1, /*login, pass*/, obj1); //Success!
//Logged in and recevied IObject1 proxy in obj1

obj1->DoSomething();
//IObject1 proxy in obj1 now tries to login under process credentials.
//Failure! E_ACCESSDENIED

CoSetProxyBlanket(obj1, /*login, pass*/); //Success!
//IObject1 proxy is now authorized.

obj1->DoSomething(); //Success!
obj1->QueryInterface(IID_IObject2, obj2); //Success!

obj2->DoSomethingElse(); //Failure!
//This different proxy for IObject2 have not yet been authorized.

CoSetProxyBlanket(obj2, /*login, pass*/);
//etc.

It's important to note that while CoCreateInstanceEx requires impersonation level to be at least IMPERSONATE, CoSetProxyBlanket doesn't seem to work on anything except IDENTIFY.

Another option is to use CoInitializeSecurity to set default credentials for the whole process. Then you don't have to call CoSetProxyBlanket on every proxy:

CoInitializeSecurity(/* login, pass */);
CoCreateInstanceEx(IID_IUnknown, /*login, pass*/, obj); //Success!
obj->DoSomething(); //Success!

When using CoInitializeSecurity on the client you have to specify asAuthSvc too, even though MSDN says you don't.

The drawback of this method is obviously that if you have several DCOM objects from different PCs you're going to have to specify all the credentials in this call and those are probably going to be tried against every computer every time you open a different proxy.

It also is not reliable when you're running from a DLL (what if a process has different default security?). So, it's probably better to implement a QueryInterface wrapper which CoSetsProxyBlanket before returning from every call.

这篇关于如何在DCOM中的模拟工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆