5

我有一个用 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 创建具有较低完整性级别的命名管道吗?我要编写什么代码来实现这一点?

4

1 回答 1

7

我不认为这是可能的。

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

请参阅此问题和答案,了解我们需要实现的目标。

从头开始编写自定义命名管道传输绑定元素似乎是目前解决此问题的唯一方法,如果失败,我们将不得不等待微软在未来版本的 WCF 中添加一些启用功能。如果您有权访问 Microsoft Connect,则可以将您的声音添加给其他请求此功能的人

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

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

抓住第一个管道手柄并非易事。WCF 将它隐藏在 type 的实例中System.ServiceModel.Channels.PipeConnectionListener.PendingAccept,存储在由管道连接侦听器维护的列表中。连接监听器和通道监听器不是一回事(可以直接通过覆盖BuildChannelListener<>绑定元素的方法),而且更难理解。它涉及使用反射来定位端点的 TransportManager,它保存对端点连接侦听器的引用,然后沿着连接侦听器链(根据跟踪等的配置而变化)工作,直到找到管道连接侦听器. 如果幸运的话,第一个管道句柄可以在侦听器的待处理接受列表中找到(尽管这里存在竞争条件 - 如果客户端在我们获得句柄之前连接,它将永远消失)。

一旦句柄可用,降低完整性以允许低完整性客户端与服务通信只是调用SetSecurityInfo句柄以添加完整性标签的问题。

我计划很快在我的博客上介绍这些细节。

于 2010-12-21T12:38:02.690 回答