Exact duplicate of
SSL error RemoteCertificateNameMismatch
SSL error RemoteCertificateNameMismatch
I am using WCF for the client to access service. I am trying to access the endpoint with TLS (https). I have certificates with both private and public keys.
If I have the end point of the service to have the host name same as the certificate name ("Issued To"), then i am able to access the service from the client.
If the names of the "issued to" and end point domain name are different i get the error "Could not establish trust relationship for the SSL/TLS secure channel with authority". I have added the certificates to "Trusted Root", "Personal" and "trusted People". In my service i have used "PeerOrChainTrust".
Please let me know if anybody has any idea on this
In that case, you need to define the trust policy for the server on client side,
Call SetCertPolicy once before you make any call to the services.
using System.Net;
using System.Security.Cryptography.X509Certificates;
public static void SetCertPolicy()
{
ServicePointManager.ServerCertificateValidationCallback += RemoteCertValidate;
}
private static bool RemoteCertValidate( object sender, X509Certificate cert, X509Chain chain,
SslPolicyErrors error )
{
// trust any cert!!!
return true;
}
Related
I am trying to implement the mTLS in cluster across micro service for secured communication. I know that there are service meshes are available for this purpose. But we would like to stay away from service mesh and implement the mTLS in cluster.
So, after going through several posts, then I am able to create the tls secret and mount the volume as part of the service deployment. This certificate i can retrieve from X509Store:
using var certificateStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine, OpenFlags.ReadOnly);
if (certificateStore.Certificates.Any())
{
var certs = certificateStore.Certificates.Find(X509FindType.FindByIssuerName, issuerName, true);
if (certs.Any())
{
return certs.First();
}
}
return null;
But, now, when i am trying to assign this certificate as part of the
kestrelServerOptions.ConfigureHttpsDefaults(listenOptions =>
{
Log.Information($"Configuring the https defaults.");
if (serverCertificate == null)
{
return;
}
// self signed certificate
Log.Information($"Before : Private key: {serverCertificate?.HasPrivateKey}");
Log.Information($"After : Server certificate: {listenOptions.ServerCertificate?.Issuer}");
listenOptions.ServerCertificate = serverCertificate; // throws exception saying that the serer certificate should have the private key.
....
my secret volume has both .crt(pem) and .key files stored as part of the tls secret. But service is not able to attach this private .key to it.
I am really lost here... and not able to proceed further.
I really appreciate if someone help me to work with this certificate and mTLS.
Thanks in advance.
Scenario:
I've a WCF web service called SERVICEA hosted in Azure. It's uses self signed certificate for HTTPS.
This SERVICEA inspect the incoming request and determines whether to call:
SERVICEB OR
SERVICEC
Both SERVICEB AND SERVICEC also uses self signed cert. for https.
PROBLEM:
When I deploy the SERVICEA and try to call so that it invokes SERVICEB I get the error message below:
*
Could not establish trust relationship for the SSL/TLS secure channel
with authority "SERVICEB..."
*.
Note it says SERVICEB.. on error message.
Anyidea how I can resolve this issue, please?
You need to validate the server certificate if its self signed as shown below:
ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, error) => true;
You want to trap the ServerCertificateValidationCallback and make it ignore certificates of your choosing.
Here is a decent article that explains how: http://blog.jameshiggs.com/2008/05/01/c-how-to-accept-an-invalid-ssl-certificate-programmatically/
Rajesh is onto something, but his answer disables certification checks altogether.
Instead I would suggest an event handler like the following should be added to your application:
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) =>
{
var request = sender as HttpWebRequest;
if (request != null && request.Address.Host == "<Your domain name goes here>")
return true;
return errors == SslPolicyErrors.None;
};
I have a specific problem that I can't solve. Let me explain in detail. I'm new to this technology so I might be using some wrong terms. Please correct and explain or ask for explanation if you don't understand.
I am creating a self hosted WCF REST server, hosted in WPF application. It uses https, SLL with WebHttpSecurityMode.Transport. I am using my own generated certificate.
I would like to create a WinForms client that would use this service. The format of the response form the server is JSON.
I would like to validate the certificate on the client with my custom validator inherited from X509CertificateValidator.
This is my server side code. I'm using a custom username validator that works fine. I have configured the certificate in the IIS Manager on my machine for the Default Website > Bindings, where I have generated the certificate (Windows 7).
WebServiceHost sh = new WebServiceHost(typeof(ReachService));
string uri = "https://localhost:9000/Service";
WebHttpBinding wb = new WebHttpBinding();
wb.Security.Mode = WebHttpSecurityMode.Transport;
wb.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
sh.AddServiceEndpoint(typeof(IReachService), wb, uri);
sh.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNameValidator();
sh.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
sh.Open();
and this is my client code
Uri uri = new Uri("https://localhost:9000/Service");
WebChannelFactory<ReachService> cf = new WebChannelFactory<IReachService>(uri);
WebHttpBinding wb = cf.Endpoint.Binding as WebHttpBinding;
wb.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
wb.Security.Mode = WebHttpSecurityMode.Transport;
cf.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
cf.Credentials.ServiceCertificate.Authentication.CustomCertificateValidator = new CustomCertificateValidator("PL2"); // this is the name that issued the certificate
cf.Credentials.UserName.UserName = "user1";
cf.Credentials.UserName.Password = "user1";
IReachService service = cf.CreateChannel();
try
{
CustomersList auth = service.GetCustomers();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
on calling service.GetCustomers() I get:
Could not establish trust relationship for the SSL/TLS secure channel with authority
'localhost:9000'.
InnerException Message:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
InnerException Message:
The remote certificate is invalid according to the validation procedure.
The server is working fine when I test in the browser.
But the client code is wrong cause it doesn't go to the custom cert validator class. And this class is the same as in the MSDN example on http://msdn.microsoft.com/en-us/library/system.identitymodel.selectors.x509certificatevalidator.aspx.
Can anyone please tell me where am I going wrong with this approach?
If you need more info please ask.
Thank you
It looks like the issue occurs because certificate was issued for some other hostname. You can check this (and customize if necessary) by providing custom ServicePointManager.ServerCertificateValidationCallback.
//don't use HttpWebRequest --you lose all of the strongly-typed method and data contracts!
//the code to create the channel and call a method:
SetCertPolicy();
var cf1 = new WebChannelFactory<TService>(new Uri(remoteServiceAddressSecure));
var service = cf1.CreateChannel();
sevice.DoMethod();
protected static void SetCertPolicy()
{
ServicePointManager.ServerCertificateValidationCallback += RemoteCertValidate;
}
private static bool RemoteCertValidate(object sender, X509Certificate cert, X509Chain chain,
SslPolicyErrors error)
{
// trust any cert!!!
return true;
}
If you want to use WCF on the client, then don't use WebHttpBinding, stick with the SOAP stuff it will work much better.
However, if you want to use a standard HTTP client like, WebClient or HttpWebRequest or HttpClient V.prototype or HttpClient V.Next then stick with the webHttpBinding.
Sorry for not addressing your direct question but you are likely to run into more problems because you are using a binding that was intended to make WCF services accessible to non-WCF platforms but then using WCF to try and access it.
I've got a WCF client and service. The service is configured to use a certificate for encryption. This is all working fine. We're using self-signed certificates for testing.
Except that one of my QA guys has deleted the certificate from his client PC and he can still connect to the service.
This leads to my question:
In Internet Explorer (and other browsers), when you're connected via HTTPS, you can see the server's certificate by clicking on the padlock icon. I'd like to do something similar in my WCF client, so that the user can verify the server's identity. Is there a way in my WCF client to get hold of the server certificate and to display it?
One way to achieve this is by using a custom certificate validator (in which case the server cert will be passed in to the Validate method, and from there you can do what you like with it (i.e. save the certificate somewhere the client can use, and then validate it using one of the default validators))
public class MyX509CertificateValidator : X509CertificateValidator
{
private readonly X509CertificateValidationMode _validationMode;
private readonly WcfClient _client;
public MyX509CertificateValidator(WcfClient client, X509CertificateValidationMode validationMode)
{
_client = client;
_validationMode = validationMode;
}
public override void Validate(X509Certificate2 certificate)
{
if (certificate == null)
{
throw new ArgumentNullException("certificate");
}
_client.ServerCertificate = certificate;
switch (_validationMode)
{
case X509CertificateValidationMode.None:
None.Validate(certificate);
return;
case X509CertificateValidationMode.PeerOrChainTrust:
PeerOrChainTrust.Validate(certificate);
return;
case X509CertificateValidationMode.PeerTrust:
PeerTrust.Validate(certificate);
return;
default:
ChainTrust.Validate(certificate);
return;
}
}
}
The encryption will use the server side certificate, just like it does for a https site.
You could use the client certificates for authentication, but this is something else.
I'm making an httpwebrequest using a public Root authority Certificat file X509. I only have the public key, not the private key. Everything works fine from a Console app but it does not work from an asp.net app. I get the error: "The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."
The option to disable Validation is not an option.
Here is the code
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://xxxxxxx/gateway.aspx");
string post = "abcdef";
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
req.ContentLength = post.Length;
var cert = System.Security.Cryptography.X509Certificates.X509Certificate.CreateFromCertFile(#"c:\temp\root.cer");
req.ClientCertificates.Add(cert);
StreamWriter stOut = new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII);
stOut.Write(post.ToString());
stOut.Close();
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Here is the System Logs from System.Net and System.Net Sockets.
System.Net Information: 0 : [5928] SecureChannel#8106798 - A certificate chain could not be built to a trusted root authority.
System.Net Information: 0 : [5928] SecureChannel#8106798 - Remote certificate was verified as invalid by the user.
System.Net.Sockets Verbose: 0 : [5928] Socket#7486778::Dispose()
System.Net Error: 0 : [5928] Exception in the HttpWebRequest#51319244:: - The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
System.Net Error: 0 : [5928] Exception in the HttpWebRequest#51319244::EndGetRequestStream - The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
Further info
If I use this code (from CodeGuru)
public static bool ValidateServerCertificate(object sender,
X509Certificate certificate, X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors ==
SslPolicyErrors.RemoteCertificateChainErrors) {
return false;
} else if (sslPolicyErrors ==
SslPolicyErrors.RemoteCertificateNameMismatch) {
System.Security.Policy.Zone z =
System.Security.Policy.Zone.CreateFromUrl
(((HttpWebRequest)sender).RequestUri.ToString());
if (z.SecurityZone ==
System.Security.SecurityZone.Intranet ||
z.SecurityZone ==
System.Security.SecurityZone.MyComputer) {
return true;
}
return false;
}
return true;
}
I ultimately get the error:
Remote Certificate Chain Error
This problem can be fixed with this added to Application_Start:
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
It basically allows for a mismatch between the server and its certificate.
Source:
http://www.ben-morris.com/asp-net-web-services-and-ssl-certificates-establishing-a-trust-relationship
Note: This workaround is not recommended for production
It sounds like the issue could be what is posted on this link. The ASPNET worker process requires the cert name to match the server name. There are work arounds that can be implemented with test environments.
For certificate generation you can use a free program called SelfSSL.exe with commands such as:
SelfSSL.exe /T /N:CN=localhost /V:999 /Q (where "localhost" is cert name)
And:
winHTTPCertCfg.exe -g -c local_machine\my -s localhost -a Administrators (to grant admins access to the cert)