using Self-Signed SSL certificate with WCF ws2007FederationBinding - wcf

I'm at my wit's end, and I'm hoping you can help me. I'm trying to get active WS-Trust authentication going with WIF from a web application to a web service, using a self-signed certificate.
I've already tried the following:
1) Install certificate in machine certificate store under Trusted Root Certification Authorities, Personal, and Trusted People
2) Make sure 'Everyone' has full access to Crypto/RSA/MachineKeys folder
3) Override certificate validation with ServicePointManager.ServerCertificateValidationCallback, to a method that just returns true. I can debug into this method and watch it return true.
And I STILL see this in the System.ServiceModel trace:
[0832] SecureChannel#66940002 - Certificate name mismatch.
[0832] SecureChannel#66940002 - Remote certificate was verified as invalid by the user.
And the application blows up with:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.

That's because the ServerCertificateValidationCallback only does the SSL related part of the certificate verification.
So if it's still broken, this means there not only SSL at play here.
In fact WS-Trust is build on top of WS-Security and WS-Security does a signature of the headers of your message,. And the verification of that signature is not impacted by ServerCertificateValidationCallback.
You certainly have a second certificate signing the WS Security headers of your message.
There's a different piece of code that verifies if the name of that certificates matches the value in the identity node of the endpoint settings, as below :
<endpoint address="..."
<identity>
<dns value="PUT CN OF THE MESSAGE SIGNATURE CERTIFICATE HERE" />
</identity>
</endpoint>
If in addition the message signature certificate doesn't validate, you can disable it's validation by modifying "behaviors/endpointBehaviors/behavior/clientCredentials/serviceCertificate/authentication".
You set the certificateValidationMode attribute there to "None".
Or you set it to Custom, and will have then to implement your own validator, that derives from System.IdentityModel.Selectors.X509CertificateValidator and overrides the Validate callback.

Related

Adding a certificate to a WCF client. Cannot find X.509 certificate

I have a WCF client that is going to authenticate against some web service using a certificate issued by said service. At first my client used a https binding as below:
var httpsBinding = new BasicHttpsBinding();
httpsBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
httpsBinding.Security.Mode = BasicHttpsSecurityMode.Transport;
but this gave the following error:
InvalidOperationException: The client certificate is not provided.
Specify a client certificate in ClientCredentials.
I then added the following code to my client configuration:
this.ChannelFactory.Credentials.ClientCertificate.SetCertificate("test", System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine,
System.Security.Cryptography.X509Certificates.StoreName.My);
And now I get the error
System.InvalidOperationException: 'Cannot find the X.509 certificate
using the following search criteria: StoreName 'My', StoreLocation
'LocalMachine', FindType 'FindBySubjectDistinguishedName', FindValue
'test'.'
I am absolutely certain that the certificate is placed in the Personal folder on my Local Machine, but it still cannot find it. I have tried placing the certificate in various folders, renaming it, using the thumbprint for identification, but my application still can't find it. What could be the issue here?
I suggest you set up the certificate by using X509FindType.FindByThumbprint.
ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
//client.ClientCredentials.ServiceCertificate.SetDefaultCertificate(StoreLocation.LocalMachine, StoreName.Root, X509FindType.FindByThumbprint, "cbc81f77ed01a9784a12483030ccd497f01be71c");
client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "9ee8be61d875bd6e1108c98b590386d0a489a9ca");
It corresponds to the below value.
In order to allow WCF service could access this local certificate, we usually add Everyone account to the management group of the certificate private key.
Besides, WCF service with authenticating the client with a certificate, this usually requires that we set up both the service certificate and the client certificate on the client-side.
Feel free to let me know if there is anything I can help with.

SOAP security negotiation failed after windows security update KB4056892

I have a server which runs this WCF service, this service worked perfectly before the new windows security update KB4056892.
The client which uses the service cannot verify the certificate, if i remove the certificate security it works perfectly. Also if i remove the windows update it will work as usual.
I've tried to change the validation method without any luck.
The certificate is not outdated and tried to test the key with an certificate utility app. The certificate chain and private key was successfully tested.
<security>
<message clientCredentialType="UserName" />
</security>
"SOAP security negotiation with 'http://servernameproduction..' for target 'http://servernameproduction..' failed. See inner exception for more details."
Innerexception: The X.509 certificate CN=xxx, O=xxx, STREET=xxx, L=xxx, S=xxx, PostalCode=xxx, C=xxx chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode. The certificate is not valid for the requested usage.
UPDATE: https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2018-0786

BizTalk WCF-BasicHttp Identity Editor field clarification

I'm trying to make it so my Send Port which is of type WCF-BasicHttp, will send a client certificate that will be accepted by the IIS server of the WCF service.
So far, as far as I can tell, the Client Cert is being attached (because when I put the wrong thumbprint value in there, I get a "Client Cert not found error"). However, now I'm getting an error as such
System.Net.WebException: The underlying connection was closed: Could
not establish trust relationship for the SSL/TLS secure channel. --->
System.Security.Authentication.AuthenticationException: The remote
certificate is invalid according to the validation procedure.
Which to me, sounds like something in processing the IIS SSL certificate is not working.
This service
works fine when being called from another Winforms application, using
the same Client Cert.
is set to Require SSL
is set to Require Client Certificates
Have a look at the image below...the only way I was able to the WCF to recognize a client cert was being attached was through configuring the send port as such:
My question is, does this look correct? Notice the highlighted field, what is supposed to go in there? Is this the reason I'm getting the SSL/TLS error?
EDIT Or, do I have it all wrong, and the lower Certificate Reference area is not supposed to contain the Client Certficate?
So, it turns out, that in order to get it to work, I had to provide the Service's identity in the top portion. I noticed that putting anything in the Endpoint Identity dialog, after saving, a nice little bit of XML is written to the WCF-BasicHttp dialog after.
<identity>
<dns value="myserver.mydomain.ca" />
<certificateReference storeName="My" storeLocation="LocalMachine" x509FindType="FindByThumbprint" findValue="[thumbprint]" isChainIncluded="False" />
</identity>
with only the lower portion filled out as in my question above, it provides the <certificateReference> portion, but the <dns value="myserver.mydomain.ca" /> does not show up until you provide something in one of the textboxes in the "General" section. It worked when I provided either the DNS, or the Base64 of the server certificate.
So, I guess the answer is, once you fill out one of the sections, both are required, the send port is not going to automatically guess on the endpoint based on the address.

How to set user principal name of service identity of an STS issuer for a ws-federation binding by config?

How can I specify the service identity principal name in the WCF client config for the issuer STS when binding using WS-Federation?
I have an application pool running under a domain account on a front end server trying to authenticate using federation to backend services on an app server (running under domain accnts) using an STS also running on the app server and under a domain account.
In order to use Kerberos correctly I need to set the userprincipal name of the STS on the frontend client. I can't see how to do that.
I am experiencing a connected problem, which is that fallback to NTLM does not work when the issuer is specified using FQDN, and Kerberos fails (SSPI negotiation failed) I think because I have no issuer principal name in the config. If I set the issuer using IP address instead, then authentication to STS succeeds using NTLM, I think, so I have a workaround.
The STS is issuing tokens on the basis of Windows auth on that endpoint. It has other endpoints for forms-type auth and so on.
Possibly a related problem on our network is that silverlight clients that call back to web services are not working without the servers being manually added to Local Intranet zone in IE. Seems as though for some reason the app servers are not considered as being on same domain. Any clues much appreciated!
I found the solution regarding setting the user principal name of the STS. I just needed to set it in the issuer element of the federation binding:
OK, don't know why I couldn't find this before, but first thing Monday morning the answer pops up immediately:
http://msdn.microsoft.com/en-us/library/aa347735.aspx
The issuer element of the wsfederation is an endpoint config that allows you to set the user principal name within it.
The schema from the link above is here:
<issuer address="Uri" >
<headers>
<add name="String"
namespace="String" />
</headers>
<identity>
<certificate encodedValue="String"/>
<certificateReference findValue="String"
isChainIncluded="Boolean"
storeName="AddressBook/AuthRoot/CertificateAuthority/Disallowed/My/Root/TrustedPeople/TrustedPublisher"
storeLocation="LocalMachine/CurrentUser"
x509FindType=System.Security.Cryptography.X509certificates.X509findtype/>
<dns value="String"/>
<rsa value="String"/>
<servicePrincipalName value="String"/>
<usePrincipalName value="String"/>
</identity>
</issuer>
Regarding the network issues, this was a DNS problem. PTR used instead of aliases.

WCF service with SSL

I know that SSL certificate is used for security purpose of application so that data transfer should be in encrypted form.As per my knowledge we have to install SSL certificate in host server for our application.
These days i am working in WCF service. Client want us to make WCF service with SSL certificate.
What i want to know that is there any need to do in code level for SSL certificate. I am going to host my service in IIS.
What are the steps for configuring WCF service with SSL certificate?
I know little knowledge is always dangerous :(
Please elaborate.
Thanks in advance.
In order to configure your service for 2 way SSL below are the steps:
Create a website which has the https binding mapped on it.
When the https binding is mapped to the website it asks for a server SSL certificate that it would use to secure your transport channel.
Create a virtual directory where you want your services to be deployed.
Now the WCF services being built need to have the configuration that specifies that the service uses https and clients are authenticated using certificates.
Set the option to "Accept" on your SSL Settings of your virtual directory which states that the client might pass a certificate. IF you set it to require then the client needs to pass a certificate.
NOTE: When using certificate you need to be sure on which certificate needs to be installed in which certificate store. You might have some exceptions with self signed certificates but they can be bypassed on client by using the code below:
ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, error) => true;
Some code on how to implement your custom certificate validator and use it:
public class CustomX509CertificateValidator : System.IdentityModel.Selectors.X509CertificateValidator
{
// This Validation function accepts any X.509 Certificate that is self-issued. As anyone can construct such
// a certificate this custom validator is less secure than the default behavior provided by the
// ChainTrust X509CertificateValidationMode. The security implications of this should be carefully
// considered before using this validation logic in production code.
public override void Validate(X509Certificate2 certificate)
{
// Check that we have been passed a certificate
if (certificate == null)
throw new ArgumentNullException("certificate");
// Only accept self-issued certificates
if (certificate.Subject != certificate.Issuer)
throw new SecurityTokenException("Certificate is not self-issued");
}
}
Now in your WCF service config file to use the custom certificate validator is shown below:
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<!--
The serviceCredentials behavior allows one to specify authentication constraints on client certificates.
-->
<clientCertificate>
<!--
Setting the certificateValidationMode to Custom means that if the custom X509CertificateValidator
does NOT throw an exception, then the provided certificate will be trusted without performing any
validation beyond that performed by the custom validator. The security implications of this
setting should be carefully considered before using Custom in production code.
-->
<authentication certificateValidationMode="Custom" customCertificateValidatorType="X509CertificateValidator.CustomX509CertificateValidator, service"/>
</clientCertificate>
<!--
The serviceCredentials behavior allows one to define a service certificate.
A service certificate is used by a client to authenticate the service and provide message protection.
This configuration references the "localhost" certificate installed during the setup instructions.
-->
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>