如何降低WCF命名管道的完整性

时间:2010-10-31 19:07:41

标签: c# wcf named-pipes bho protected-mode

我有一个用C#编写的Internet Explorer加载项,它通过WCF命名管道与.NET桌面应用程序进行通信。桌面应用程序为netNamedPipeBinding创建ServiceHost,IE加载项的每个实例都创建一个ChannelFactory以与应用程序通信。在Windows XP下一切正常,但在Windows 7的IE保护模式下会抛出异常。

System.ServiceModel.CommunicationException:无法连接到端点'net.pipe://localhost/MyApp.MyID'。 ---> System.IO.PipeException:'\。\ pipe ... guid ...'存在管道端点,但连接失败:访问被拒绝。 (5,0x5)

在受保护模式下运行加载项是我必须支持的方案。我的理解是,如果我降低命名管道的完整性级别,那么我的IE加载项将被允许通过它进行通信。我的问题是如何做到这一点。我有设置使用WCF的东西,并且最好是保持这种方式。我可以让WCF创建具有较低完整性级别的命名管道吗?我写了什么代码才能实现这一目标?

1 个答案:

答案 0 :(得分:7)

我认为这不可能。

问题是必须在创建命名管道时提供的安全描述符中指定完整性标签。在标准的NetNamedPipeBinding中,对CreateNamedPipe的调用发生在内部WCF类CreatePipe()的私有System.ServiceModel.Channels.PipeConnectionListener方法内。我看不到改变它为管道指定初始安全描述符的方法。

请参阅this question and answer,了解我们需要实现的目标。

从头开始编写自定义命名管道传输绑定元素似乎是目前解决此问题的唯一方法,如果失败,我们只需要等待Microsoft在未来版本的WCF中添加一些启用功能。如果您有权访问Microsoft Connect,则可以add your voice to the others requesting this feature

编辑: 我太悲观了。我现在找到了一种方法来做到这一点。

关键是,当创建管道时,你不必在安全描述符中指定完整性标签 - 但是你必须使用从CreateNamedPipe返回的句柄在打开监听器时修改SACL - 即管道的第一个服务器端句柄。使用任何其他句柄,添加完整性标签的尝试总是失败,因为dwOpenMode的{​​{1}}标志参数重载使用其中一个位来表示CreateNamedPipe和{{1} }}。我们需要后者的访问权限才能添加完整性标签,但前者的存在会导致调用在除第一个管道实例之外的任何管道上失败。

掌握第一个管道手柄并非易事。 WCF将其放在类型FILE_FLAG_FIRST_PIPE_INSTANCE的实例中,存储在由管道连接侦听器维护的列表中。连接侦听器与通道侦听器不同(可以通过覆盖绑定元素的WRITE_OWNER方法直接获取),并且更难以实现。它涉及使用反射的英雄,定位端点的TransportManager,它保存对端点的连接侦听器的引用,然后处理连接侦听器链(根据跟踪的配置等而变化),直到找到管道连接侦听器。如果我们很幸运,那么第一个管道句柄就可以在监听器的挂起接受列表中找到(虽然这里存在竞争条件 - 如果客户端在我们抓住句柄之前连接,它将永远消失)。

一旦句柄可用,降低完整性以允许低完整性客户端与服务进行通信只需在句柄上调用System.ServiceModel.Channels.PipeConnectionListener.PendingAccept来添加完整性标签。

我计划很快介绍my blog上的一些细节。