Named Pipe Transport Security
Hello,
I am attempting to enable transport security over a named pipe binding and I'm receiving the following error:
System.ServiceModel.Security.SecurityNegotiationException: The server has rejected the client credentials. > System.Security.Authentication.InvalidCredentialException: The server has rejected the client credentials. > System.ComponentModel.Win32Exception: The logon attempt failed
End of inner exception stack trace
at System.Net.Security.NegoState.ProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.NegotiateStream.AuthenticateAsClient(NetworkCredential credential, String targetName, ProtectionLevel requiredProtectionLevel, TokenImpersonationLevel allowedImpersonationLevel)
at System.ServiceModel.Channels.WindowsStreamSecurityUpgradeProvider.WindowsStreamSecurityUpgradeInitiator.OnInitiateUpgrade(Stream stream, SecurityMessageProperty& remoteSecurity)
End of inner exception stack trace
This is my binding:
<netNamedPipeBinding>
<
bindingname="PrivateServiceBinding"closeTimeout="00:00:20"receiveTimeout="00:00:30"sendTimeout="00:00:30">
<securitymode="Transport" />
</binding>
</netNamedPipeBinding>
If I switch to a TCP binding, my service works:
<netTcpBinding>
<
bindingname="PrivateServiceBinding"closeTimeout="00:00:20"receiveTimeout="00:00:30"sendTimeout="00:00:30">
<securitymode="Transport">
<transportclientCredentialType="Windows"protectionLevel="EncryptAndSign" />
</security>
</binding>
</netTcpBinding>
Client and server are on the same machine. Any idea why I'd be seeing a failure with named pipes? Several of my services are local only, but they require impersonation.
I'd prefer to use named pipes if possible for performance reasons. And, my services are hosted in different app domains within the same process, so going TCP would require me to eat up a lot of ports or require the user to enable the port sharing service.
This part sounds like what I need:
"However, if the target SPN passed to SSPI is a well formed SPN for the local computer account (e.g. host/[dns machine name]) then Negotiate will use NTLM (loopback optimization) and the access token will not have the Network SID (and therefore will be usable with NetNamedPipes)."
So, I need to get it to use NTLM. What is the procedure for setting the SPN to achieve this? I tried specifying an identity on my service endpoint to match the hostname, but I still received the same error.
Thanks, but unfortunately that didn't work either. I tried both formats. Here's a sample configuration that approximates my setup. Spot anything amiss?
<system.serviceModel>
<client>
<endpoint
address="net.pipe://MyRoot/Service"
binding="netNamedPipeBinding" bindingConfiguration="PrivateServiceImpersonationBinding"
behaviorConfiguration="PrivateClientBehavior"
contract="IService"
name="Service">
<identity>
<servicePrincipalName value="MYSERVER$"/>
</identity>
</endpoint>
</client>
<services>
<service name="Service" behaviorConfiguration="PrivateServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.pipe://MyRoot/Service" />
</baseAddresses>
</host>
<endpoint binding="netNamedPipeBinding" bindingConfiguration="PrivateServiceImpersonationBinding"
name="ServiceEndpoint" contract="IService"
listenUriMode="Explicit">
<identity>
<servicePrincipalName value="MYSERVER$"/>
</identity>
</endpoint>
</service>
</services>
<bindings>
<netNamedPipeBinding>
<binding name="PrivateServiceImpersonationBinding" closeTimeout="00:00:20"
receiveTimeout="00:00:30" sendTimeout="00:00:30">
<security mode="Transport" />
</binding>
</netNamedPipeBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="PrivateClientBehavior">
<clientCredentials>
<windows allowedImpersonationLevel="Impersonation" />
</clientCredentials>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="PrivateServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
aha - Kenny's post was about domain environments...
Then I don't understand the problem. I have the same test setup here and it works fine.
Try localhost as the machine name.
<client>
<endpoint address="net.pipe://localhost/PetShop"
binding="netNamedPipeBinding"
contract="IPetStore" />
</client>
and
<client>
<endpoint address="net.pipe://localhost/PetShop"
binding="netNamedPipeBinding"
contract="IPetStore" />
</client>