WCF + net.tcp binding + certificates = Communication object is in theFaulted state

W

WolfMoon

Hi All.
We are recently in my company working on a large system. It is suppose
to have 3 layers (presentation - ASP.NET, middle - WCF server, and
data - Oracle). As you can see, middle layer, WCF server, is suppose
to separate database from potentially untrusted ASP server.
To provide security to web server - WCF server (called AppServer)
connection and make it as fast, as possible, we decided to use net.tcp
protocol/binding for communication. As we know, this protocol is
encrypted as default. One can choose either Windows Authentication,
user/pass or certificates. User/Pass is good... but it has no use for
package level encryption (one should still provide some way to encrypt
package, usually by X509 certificate). Windows authentication can't be
used, as target company has no windows domain server. Certificates are
the only option.

After 2 days of struggle with certificates (multiple "how to" pages
and blogs, all showing different way how to do it, or how generate
certificate for development use, usually doesn't working or suitable
only for solutions where both server and client are on the same
machine) I figured out how to do it (thanks MitchDanny for this post:
http://notgartner.wordpress.com/200...on-with-windows-communication-foundation-wcf/
).
Well, it almost works. I switched certificate related errors to a
different ones.

Whole solution was working fine, without certificates, on one machine.
Now it acts weird (still on one machine). One test method works, the
other, much more important, throws infamous "The communication object,
System.ServiceModel.Security.SecuritySessionClientSettings`1+ClientSecurityDuplexSessionChannel[System.ServiceModel.Channels.IDuplexSessionChannel],
cannot be used for communication because it is in the Faulted state"

Certificates generated using command lines:
makecert.exe -pe -ss My -sr LocalMachine -a sha1 -sky exchange -n
CN=ServerSide
makecert.exe -pe -ss My -sr LocalMachine -a sha1 -sky exchange -n
CN=ClientSide

then exported and imported to "Trusted People" storage, under "Local
Machine" registry.

Service contract:

<ServiceContract()> _
Public Interface IDPSAppService

''' <summary>
''' Returns DataTable filled with simple select query from
database
''' </summary>
<OperationContract(Action:="GetData")> _
Function GetData() As DataTable

''' <summary>
''' Returns GetData() serialized to Xml as string, to test, if
DataTable object doesn't cause any problems
''' </summary>
<OperationContract(Action:="GetDataAsXml")> _
Function GetDataAsXml() As String

''' <summary>
''' Returns simply "Hello World!"
''' </summary>
<OperationContract(Action:="HelloWorld")> _
Function HelloWorld() As String
End Interface

Server configuration:

<!-- WCF configuration -->
<system.serviceModel>

<!-- Service -->
<services>
<service name="AppServerLogic.DPSAppService"
behaviorConfiguration="AppServerBehavior">
<endpoint address="net.tcp://localhost:7979/AppServer"
binding="netTcpBinding"
bindingConfiguration="AppSrvTCPBinding"
contract="DPSAppServerCommon.IDPSAppService">
</endpoint>
</service>
</services>

<!-- Binding config -->
<bindings>
<netTcpBinding>
<binding name="AppSrvTCPBinding">
<security mode="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</netTcpBinding>
</bindings>

<!--Behavior (certificate) -->
<behaviors>
<serviceBehaviors>
<behavior name="AppServerBehavior">
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</clientCertificate>
<serviceCertificate findValue="ServerSide"
x509FindType="FindBySubjectName"
storeLocation="LocalMachine" storeName="My"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>

</system.serviceModel>


Client side code for invoking methods:

factory = New ChannelFactory(Of IDPSAppService)("AppServerConfig")
client = factory.CreateChannel()
Debug.WriteLine(client.HelloWorld())
Dim dt As DataTable = New DataTable()
dt.ReadXml(New System.IO.StringReader(client.GetDataAsXml()))
dt = client.GetData()

Client configuration:

<system.serviceModel>

<client>
<endpoint address="net.tcp://localhost:7979/AppServer"
behaviorConfiguration="AppServerClientBehavior"
binding="netTcpBinding"
bindingConfiguration="AppSrvTCPBinding"
contract="DPSAppServerCommon.IDPSAppService"
name="AppServerConfig">
<identity>
<dns value="ServerSide" />
</identity>
</endpoint>
</client>

<!--Binding config-->
<bindings>
<netTcpBinding>
<binding name="AppSrvTCPBinding" closeTimeout="00:10:00">
<security mode="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</netTcpBinding>
</bindings>


<!--Endpoint behavior (certificates)-->
<behaviors>
<endpointBehaviors>
<behavior name="AppServerClientBehavior">
<clientCredentials>
<clientCertificate findValue="ClientSide"
x509FindType="FindBySubjectName"
storeLocation="LocalMachine"
storeName="My"/>
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</serviceCertificate>
</clientCredentials>

</behavior>
</endpointBehaviors>
</behaviors>

</system.serviceModel>

Now, what is strange ?
If I invoke client.HelloWorld() method, I get "Hello World!", as I was
suppose to. But whenever I invoke either client.GetData() or
client.GetDataAsXml(), it is invoked on server side (I get server
debug console message), but nothing is returned and exception is
thrown on client side.
Exception:

The communication object,
System.ServiceModel.Security.SecuritySessionClientSettings`1+ClientSecurityDuplexSessionChannel[System.ServiceModel.Channels.IDuplexSessionChannel],
cannot be used for communication because it is in the Faulted state

I guess, everyone who had anything to do with WCF knows this
exception. It covers any useful data, showing nothing (inner exception
is empty, of course).
I guess, it has to do something with security (general
SecuritySessionClientSettings class), but maybe I missed something
(like some special attributes in contract or some
ServiceContractAttribute or OperationContractAttribute parameters).
If anybody had such a situation and found a solution, please, share it
with me (and others seeking help).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top