简体   繁体   English

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

[英]How to lower integrity of WCF named pipe

I have an Internet Explorer add-in, written in C#, which talks via a WCF named-pipe to a .NET desktop application. 我有一个用C#编写的Internet Explorer加载项,它通过WCF命名管道与.NET桌面应用程序进行通信。 The desktop app creates the ServiceHost for the netNamedPipeBinding, and each instance of the IE add-in creates a ChannelFactory to talk to the app. 桌面应用程序为netNamedPipeBinding创建ServiceHost,IE加载项的每个实例都创建一个ChannelFactory以与应用程序通信。 Everything works fine under Windows XP, but an exception is thrown under IE's protected mode in Windows 7. 在Windows XP下一切正常,但在Windows 7的IE保护模式下会抛出异常。

System.ServiceModel.CommunicationException: Cannot connect to endpoint 'net.pipe://localhost/MyApp.MyID'. System.ServiceModel.CommunicationException:无法连接到端点'net.pipe://localhost/MyApp.MyID'。 ---> System.IO.PipeException: A pipe endpoint exists for '\\.\\pipe...guid...', but the connect failed: Access is denied. ---> System.IO.PipeException:'\\。\\ pipe ... guid ...'存在管道端点,但连接失败:访问被拒绝。 (5, 0x5) (5,0x5)

Running the add-in under protected mode is a scenario I must support. 在受保护模式下运行加载项是我必须支持的方案。 My understanding is that if I lower the integrity level of the named-pipe, then my IE add-in will be allowed to talk through it. 我的理解是,如果我降低命名管道的完整性级别,那么我的IE加载项将被允许通过它进行通信。 My question is how to do that. 我的问题是如何做到这一点。 I have things setup to use WCF, and would preferably like to keep it that way. 我有设置使用WCF的东西,并且最好是保持这种方式。 Can I make WCF create the named pipe with the lower integrity level? 我可以让WCF创建具有较低完整性级别的命名管道吗? What code do I write to make that happen? 我写了什么代码来实现这一目标?

I don't think this is going to be possible. 我不认为这是可能的。

The problem is that the integrity label has to be specified in the security descriptor provided when the Named Pipe is created. 问题是必须在创建命名管道时提供的安全描述符中指定完整性标签。 In the standard NetNamedPipeBinding, that call to CreateNamedPipe happens inside the private CreatePipe() method of the internal WCF class System.ServiceModel.Channels.PipeConnectionListener . 在标准的NetNamedPipeBinding中,对CreateNamedPipe调用发生在内部WCF类System.ServiceModel.Channels.PipeConnectionListener的私有CreatePipe()方法中。 I can't see a way to change how it specifies the initial security descriptor for the pipe. 我看不到改变它如何为管道指定初始安全描述符的方法。

See this question and answer for an outline of what we need to achieve. 请参阅此问题和答案 ,了解我们需要实现的目标。

Writing a custom named pipe transport binding element from scratch seems like the only way at present to get round this, failing which we'll just have to wait for Microsoft to add some enabling features in a future version of WCF. 从头开始编写自定义命名管道传输绑定元素似乎是目前解决此问题的唯一方法,否则我们只需要等待Microsoft在未来版本的WCF中添加一些启用功能。 If you have access to Microsoft Connect, you could add your voice to the others requesting this feature . 如果您有权访问Microsoft Connect,则可以将您的语音添加到请求此功能的其他人

EDIT: I was too pessimistic. 编辑:我太悲观了。 I have now found a way to do this. 我现在找到了一种方法来做到这一点。

The key was that it turned out you don't necessarily have to specify the integrity label in the security descriptor when the pipe is created - but you do have to modify the SACL using the handle returned from CreateNamedPipe when the listener is opened - ie the very first server-side handle to the pipe. 关键是,事实证明,在创建管道时,您不一定必须在安全描述符中指定完整性标签 - 但是当打开侦听器时,您必须使用从CreateNamedPipe返回的句柄来修改SACL - 即管道的第一个服务器端句柄。 Using any other handle, the attempt to add the integrity label always fails, because the dwOpenMode flag parameter to CreateNamedPipe overloads the use of one of the bits to mean both FILE_FLAG_FIRST_PIPE_INSTANCE and WRITE_OWNER . 使用任何其他句柄,添加完整性标签的尝试总是失败,因为CreateNamedPipedwOpenMode标志参数重载使用其中一个位来表示FILE_FLAG_FIRST_PIPE_INSTANCEWRITE_OWNER We need the latter access permission in order to add the integrity label, but the presence of the former causes the call to fail on any but the first pipe instance. 我们需要后一个访问权限才能添加完整性标签,但前者的存在会导致调用在除第一个管道实例之外的任何一个上失败。

Getting hold of the first pipe handle is not a trivial undertaking. 抓住第一个管道并不是一项微不足道的工作。 WCF squirrels it away in an instance of the type System.ServiceModel.Channels.PipeConnectionListener.PendingAccept , stored in a list maintained by the pipe connection listener. WCF将其放在System.ServiceModel.Channels.PipeConnectionListener.PendingAccept类型的实例中,存储在由管道连接侦听器维护的列表中。 The connection listener is not the same thing as the channel listener (which can be grabbed straightforwardly by overriding the BuildChannelListener<> method of a binding element), and it is much harder to get at. 连接侦听器与通道侦听器不同(可以通过覆盖绑定元素的BuildChannelListener<>方法直接获取),并且更难以实现。 It involves heroics using reflection, to locate the TransportManager for the endpoint, which holds a reference to the endpoint's connection listener, and then working down a chain of connection listeners (which varies according to configuration of tracing etc) until the pipe connection listener is found. 它涉及使用反射的英雄,定位端点的TransportManager,它保存对端点的连接侦听器的引用,然后处理连接侦听器链(根据跟踪的配置等而变化),直到找到管道连接侦听器。 If we are lucky the first pipe handle can then be found in the listener's pending accept list (though there is a race condition here - if a client connects before we get hold of the handle, it will be gone forever). 如果我们幸运的话,那么第一个管道句柄就可以在监听器的挂起接受列表中找到(虽然这里存在竞争条件 - 如果客户端在我们抓住句柄之前连接,它将永远消失)。

Once the handle is available, lowering the integrity to allow low integrity clients to communicate wth the service is just a matter of calling SetSecurityInfo on the handle to add the integrity label. 一旦句柄可用,降低完整性以允许低完整性客户端与服务进行通信只需在句柄上调用SetSecurityInfo来添加完整性标签。

I plan to cover this is some detail on my blog soon. 我计划尽快在我的博客上介绍这个细节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM