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
. 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. If you have access to Microsoft Connect, you could add your voice to the others requesting this feature.
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 - i.e. the very first server-side handle to the pipe. 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
. 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. 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. 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. 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.
I plan to cover this is some detail on my blog soon.