我在使用基于 COM 的客户端-服务器设置时遇到问题。 COM 服务器是用 C# (.NET 4.0) 编写的,并作为(已注册的)本地服务器运行。
根据连接到服务器的应用程序,其他客户端将收到服务器执行失败(HRESULT异常:0x80080005(CO_E_SERVER_EXEC_FAILURE)
解释了根本问题here (in the section COM is integrity aware) .据我了解,这是由于提升的应用程序创建了具有更高完整性级别的服务器这一事实引起的。当另一个非提升的应用程序随后连接时,不允许连接到同一实例。当非提升的应用程序创建进程,然后是提升的应用程序连接时,也会发生同样的情况。
我已尝试实现 page 中描述的解决方案:修改注册表以设置应允许所有客户端连接的安全描述符。有一个 code sample在 C++ 中,但这在 .NET 中实际上做同样的事情:
// Security Descriptor with NO_EXECUTE_UP
var sd = new RawSecurityDescriptor("O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)");
byte[] securityDescriptor = new Byte[sd.BinaryLength];
sd.GetBinaryForm(securityDescriptor, 0);
RegistryKey key = Registry.ClassesRoot.OpenSubKey("AppID\\{APP-ID-GUID}", true);
if (key == null)
{
key = Registry.ClassesRoot.CreateSubKey("AppID\\{APP-ID-GUID}");
}
using (key)
{
key.SetValue("LaunchPermission", securityDescriptor, RegistryValueKind.Binary);
}
然而,这并没有达到预期的效果。当第二个客户端尝试创建相关对象的实例时,Windows 尝试启动我的 COM 服务器的单独实例,但服务器阻止两个实例以同一用户身份运行。考虑到我设置的权限,我不希望首先启动第二个实例。
由于其中一个客户端应用程序在中等 IL 中运行,而另一个在高 IL 中运行,因此我还在 mandatory label 上尝试了变体,比如:
O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;ME)
O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)(ML;;NX;;;ME)(ML;;NX;;;HI)
我还尝试按照页面上的建议将 ROTFlags
注册表项设置为 0x1 (ROTFLAGS_ALLOWANYCLIENT),但行为仍然没有变化。
我已确定以某种方式使用了 LaunchPermission 注册表值。我无法使用 Process Monitor 发现它在何处被读取,但是当我使用 dcomcnfg.exe
工具设置相同的 key 时,我可以通过拒绝启动权限来强制服务器加载失败。
我想指出我的服务器进程不需要提升。如何使提升和非提升进程都能够连接到单个服务器实例?
最佳答案
根据 Windows Vista Security Model Analysis您将需要使用共享对象(例如命名管道)在不同的 IL 之间移动。此外,共享对象的 IL 应与您正在使用的最低 IL 等效。
关于c# - 允许连接到完整性级别不匹配的 .NET COM 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12039624/