views:

943

answers:

2

[Update] - I attach also full config files, for service, and for client (outside of here, not to flood the topic)

I'm having situation pretty much identical to the one outlined in this question, however my question is somewhat different.

  • I'm using NetTcpBinding with security set to TransportWithMessageCredential
  • I'm using Password/Username credentials backed up by ASP.NET provider
  • My service is self hosted in Windows Service
  • I do have in my endpoint behavior specified authentication revocationMode="NoCheck"

It is required that the service provides a certificate to authenticate itself to clients. That's OK, I just do:

<serviceCertificate findValue="***"
                    storeLocation="CurrentUser"
                    storeName="My"
                    x509FindType="FindByThumbprint"/>

Now, I somewhat imagined that now the client would end up having

<identity>
  <certificate encodedValue="encoded certificate"/>
</identity>

And it will be able to verify service's credentials without having that certificate installed in the store on client machine.

I was surprised to learn that although I set the service credentials to certificate, WSDL exposes

<Identity>
   <Dns>Foo</Dns>
</Identity>

Again, on service I can set Identity to CertificateReference and hook it up to the same certificate, and then WSDL will expose identity as X509Certificate, but when I run the client that setting is ignored, and I end up with error message:

System.ServiceModel.Security.SecurityNegotiationException: The X.509 certificate CN=xxx is not in the trusted people store. The X.509 certificate CN=xxx chain building failed. The certificate that was used has a trust chain that can not be verified. Replace the certificate or change the certificateValidationMode. A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider.

Is there a way to make client use that value from config and work without having to install a service certificate (nor its root) on client' machine?

[UPDATE] While setting certificateValidationMode to none will make the exception go away, it is unacceptable solution from security point of view.

It makes the client merely acknowledge that it receive ''some'' certificate, without getting into details. This makes all range of man in the middle attacks possible. It still won't validate the information sent by (alleged) service against the certificate dumped in the config.

A: 

Hi, You are corect and almost finished configuring the client configuration. You are missing one last thing (as mentioned in the error description) : you need to set the revocationMode to NoCheck in the configuration:

 <behaviors>
  <endpointBehaviors>
    <behavior name="SecureMessageUserName">
      <clientCredentials>
         <serviceCertificate>
            <authentication revocationMode="NoCheck"/>
         </serviceCertificate>
      </clientCredentials>
    </behavior>
  </endpointBehaviors>
 </behaviors>

If you need more details, just let me know and I'll post a full working client configuration.

Edit sorry for the delay

You should also add the noCheck in the server configuration :

<behavior name="X509SecureBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <serviceCertificate storeName="My" storeLocation="CurrentUser" x509FindType="FindByThumbprint" findValue="aaaa" />
            <clientCertificate>
              <authentication certificateValidationMode="None" revocationMode="NoCheck" />
            </clientCertificate>
          </serviceCredentials>
        </behavior>

Also I didn't include the certificate reference in the endpoint definition.

AlexDrenea
Sorry, I forgot to mention that I do have this option set. I updated the question accordingly.Anyway, the certificate seems to be ignored regardless of what I specify here.
Krzysztof Koźmic
could you post a full configuration file ? or the significant part of it ?
AlexDrenea
Sure I can, I linked them, because they are pretty big, and I don't want to scare off potentially helpful people by drowning them in tons of xml
Krzysztof Koźmic
I'm not grumbling, but this solution does not cut it for me :(
Krzysztof Koźmic
I'm not sure I understand wht you mean? It doensn't work or you can't edit the server's config from other reasons?
AlexDrenea
Take a look at my updated question (at the bottom). Basically it does make the exception go away, and calls to succeed but it does not make the client use the certificate serialized in config - it just makes it accept ANY certificate, which is unacceptable unfortunately :/
Krzysztof Koźmic
+1  A: 

Solution sketch:

1) Define and register a custom X509CertificateValidator on the client

2) In the Validate method, compare the given certificate with the one present in the client's EndpointAddress.Identity property. The object referenced by this property should have the X509CertificateEndpointIdentity exact type.

I didn't test this solution, however it makes perfect sense to me.

HTH Pedro

Pedro Felix
This is what I ended up doing. I have a question though - why does it not work out of the box? If the client has all the required information, and receives some certificate from a service, it is the most natural thing to do to validate one against the other. Why doesn't WCF do this?
Krzysztof Koźmic
Conjecture: for security reasons. Using the proposed solution, the WSDL import process security becomes even more critical, since no additional certificate verification will be performed when communicating with the service.
Pedro Felix