Search code examples
wcfauthenticationmessagenettcpbinding

Trustchain error NetTcpBinding with message (username) security


After a week(!) of searching, I hope someone is able to tell me what I'm doing wrong.

I keep on getting the following error message:

The X.509 certificate CN=localhost chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode.

To start from the beginning. This is my code/config serverside:

ServiceHost svcHost = new ServiceHost(typeof(TestService));          

// Enable metadata publishing.
ServiceMetadataBehavior smb = svcHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (smb == null)
    smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
svcHost.Description.Behaviors.Add(smb);

ServiceDebugBehavior sdb = svcHost.Description.Behaviors.Find<ServiceDebugBehavior>();
if (sdb == null) { sdb = new ServiceDebugBehavior(); svcHost.Description.Behaviors.Add(sdb); }
sdb.IncludeExceptionDetailInFaults = true;

// Meta data servicepoint
svcHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");

// Credentials          
CustomUserNamePasswordValidator clientAuthenticationValidator = new TCustomUserNamePasswordValidator();
svcHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
svcHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = (UserNamePasswordValidator) clientAuthenticationValidator;

// Certificate
svcHost.Credentials.ServiceCertificate.Certificate = new X509Certificate2("TestServer.pfx", "password");        
svcHost.Credentials.IssuedTokenAuthentication.CertificateValidationMode = X509CertificateValidationMode.ChainTrust;
svcHost.Credentials.IssuedTokenAuthentication.RevocationMode = X509RevocationMode.None;
svcHost.Credentials.IssuedTokenAuthentication.TrustedStoreLocation = StoreLocation.LocalMachine;

// Binding
NetTcpBinding netTcpBinding = new NetTcpBinding();
netTcpBinding.Security.Mode = SecurityMode.Message;            
netTcpBinding.Security.Transport.ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign;
netTcpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
netTcpBinding.ReliableSession.Enabled = true;
svcHost.AddServiceEndpoint(typeof(ITestService), netTcpBinding, "");

svcHost.Open();

With the following app.config file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <services>
            <service name="TestService">
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8080/" />
                        <add baseAddress="net.tcp://localhost:9595" />
                    </baseAddresses>
                </host>
            </service>
        </services>      
    </system.serviceModel>
</configuration>

The following commands I used to get the certificates:
Root CA:

makecert.exe -n "CN=TestCA" -r -pe -a sha512 -len 4096 -cy authority -sr LocalMachine -ss Root -sv TestCA.pvk TestCA.cer pvk2pfx.exe -pvk TestCA.pvk -spc TestCA.cer -pfx TestCA.pfx -po aaaaa

Service:

makecert.exe -n "CN=localhost" -iv TestCA.pvk -ic TestCA.cer -pe -a sha512 -len 4096 -b 12/14/2014 -e 01/01/2020 -sky exchange -eku 1.3.6.1.5.5.7.3.1 -sv TestServer.pvk TestServer.cer pvk2pfx.exe -pvk TestServer.pvk -spc TestServer.cer -pfx TestServer.pfx -po aaaaa

Where I imported TestCA.cer in Trusted Root CA and, as shown in code, the pfx file is used as servicecertificate.

As far as I understood, I do not have to give a certificate for the client, since it uses username credentials to authenticate itself, where the servicecertificate is used for ssl. As said, as soon as I start up the client and call a function, I get the above exception.

I already tried to attach the TestServer certificate to the 9595 port with netsh. I run both client and service on the same computer.

I truly hope someone can help.


Solution

  • The issues is most likely caused by a self-signed certificate that is not “trusted” by the client. In order to accommodate this scenario, you have a few options:

    1. Import the self-signed certificate into the client machine’s “Trusted People” store.
    2. Follow the MSDN guidance to Create and Install Temporary Certificates in WCF for Message Security During Development
    3. Update the client software to bypass the certificate verification check as defined here.