Reputation: 1138
I am trying to call a web service that is deployed on a Linux Server that has a self-signed certificate from an application developed in .net core and deployed on an IIS server (Windows server 2012).
But when I try to call the endpoint the next error is thrown:
"Message": "The SSL connection could not be established, see inner exception.", "Description": "InnerError : System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception. ---> System.ComponentModel.Win32Exception: Mensaje recibido inesperado, o bien su formato es incorrecto\r\n --- End of inner exception stack trace ---\r\n at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)\r\n at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)\r\n at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)\r\n at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)\r\n at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)\r\n at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Net.Security.SslState.ThrowIfExceptional()\r\n at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)\r\n at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)\r\n at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)\r\n at System.Net.Security.SslStream.<>c.b__47_1(IAsyncResult iar)\r\n at System.Threading.Tasks.TaskFactory
1.FromAsyncCoreLogic(IAsyncResult iar, Func
2 endFunction, Action1 endAction, Task
1 promise, Boolean requiresSynchronization)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken) | stackTrace : at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)\r\n at System.Threading.Tasks.ValueTask1.get_Result()\r\n at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Threading.Tasks.ValueTask
1.get_Result()\r\n at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask1 creationTask)\r\n at System.Threading.Tasks.ValueTask
1.get_Result()\r\n at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)\r\n at ReservasProxy.Data.APIConnection.CallXMLFormDataApiPostAsyc(String body) in C:\gitProjects\ResevasProxy\ReservasProxy\ReservasProxy\Data\APIConnection.cs:line 181\r\n
I already try the next solutions but they didn´t work.
Solution 1 :
using (var httpClientHandler = new HttpClientHandler())
{
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
// Make your request...
//send request
using (var httpClient = new HttpClient(httpClientHandler))
{
var content = new StringContent(body, Encoding.UTF8, "application/soap+xml");
HttpResponseMessage response = await httpClient.PostAsync(_url, content);
//var res = await response.Content.ReadAsAsync<T>();
}
}
Solution 2:
//send request
using (var httpClient = new HttpClient())
{
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
var content = new StringContent(body, Encoding.UTF8, "application/soap+xml");
HttpResponseMessage response = await httpClient.PostAsync(_url, content);
}
Solution 3: Trying to import the certificate and then make the call but still not working.
const string certPath = @"C:\soaProdcer.cer";
var handler = new HttpClientHandler
{
ClientCertificateOptions = ClientCertificateOption.Manual,
SslProtocols = System.Security.Authentication.SslProtocols.Tls
};
handler.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate(certPath));
//send request
using (var httpClient = new HttpClient(handler))
{
var content = new StringContent(body, Encoding.UTF8, "application/soap+xml");
HttpResponseMessage response = await httpClient.PostAsync(_url, content);
}
I got the certificate using OpenSSL
>openssl s_client -showcerts -connect serversoa:443
No client certificate CA names sent
---
SSL handshake has read 774 bytes and written 493 bytes
---
New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1
Cipher : RC4-SHA
Session-ID: 4E0F69C75B8F041101562F7E9B3EA349
Session-ID-ctx:
Master-Key: 61A916A9B8AF26281B5F7A0138DF5E4C2A4B83995E0B3FDD2274BAD0D8E3C2B5E98AA7CCB48A6543F6814C2540B18848
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1558979896
Timeout : 300 (sec)
Verify return code: 18 (self signed certificate)
I imported the certificate into the IIS server into the trusted root certification authorities.
Upvotes: 2
Views: 18314
Reputation: 1138
As Ilya said it wasn´t a problem with the certificate CA authority. The problem was that the client was trying to use a different version of TLS (1.2) The solution was to specify the TLS version.
using (var httpClientHandler = new HttpClientHandler())
{
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
httpClientHandler.SslProtocols = System.Security.Authentication.SslProtocols.Tls;
//send request
using (var httpClient = new HttpClient(httpClientHandler))
{
var content = new StringContent(body, Encoding.UTF8, "application/soap+xml");
HttpResponseMessage response = await httpClient.PostAsync(_url, content);
}
}
I used Wireshark to sniffer the traffic and see what was going on...
Client sending hello with version, not supported
The server closing the connection
After finishing the test in my computer and the tests were successful I deploy the application on IIS server. When I started testing my application on the server it started throwing the same exception as before.
Why?
It turned out that the server had deactivated the cipher (RC4) As the next figure shows.
So if you are using Windows like me you just need to check the ciphers that the certificate is using. As I mentioned before the Linux server was using a CR4 cipher in the certificate
Upvotes: 2
Reputation: 30355
The error does not indicate a trouble with the certificate CA authority, but rather a response from a server that is not expected for the TLS to be established.
As the author has figured out the client supported 1.2 and the server 1.0 and it caused the trouble.
P.S. I would recommend using only TLS 1.2 if that is the option with browser support that you need to handle. (only old versions do not support 1.2.)
Upvotes: 1
Reputation: 485
I don't remember exactly the link of Microsoft tell you about this. Your above solutions work well with older asp.net core version. This is my solution with the latest ASP.NET Core that I've implemented for my project. I hope it helps you.
services.AddHttpClient<IYourService, YourService>()
.ConfigurePrimaryHttpMessageHandler(sp => new HttpClientHandler
{
AllowAutoRedirect = false,
ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true,
SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12
});
Please also read about HttpClientFactory: https://learn.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
Upvotes: 5