Webpage sometimes cannot connect to other url with SSL - c#

We have an application (WebAPI, let's name it "X") working on IIS on Windows Server 2012 R2. Sometimes "X" cannot connect to other independent API's on the web. We got error:
The underlying connection was closed: Could not establish trust
relationship for the SSL/TLS secure channel.
The remote certificate is invalid according to the validation
procedure.
I've done some testing and at the same time "X" cannot download https://google.com (using WebClient class) but I can browse it with web browser on that current server.
Also I tried to ignore server certificate errors for whole application (code below) but it didn't help too.
protected void Application_Start()
{
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
}
My clients have no problem connecting to "X". Also when the error occures on one server I am able to successfully connect (https://google.com for example) on other servers with different instance of "X".
What could be wrong?

It sounds like your IIS web application is running under a user context that doesn't have access to the certificates on the machine. However, the browser is running under a different user context that does have access. That explains your test results.
If the user does have access to the certificates, then possibly you will need to download the certificates from the independent API's. See this: http://brainof-dave.blogspot.com.au/2008/08/remote-certificate-is-invalid-according.html
Check out these resources too:
https://blogs.msdn.microsoft.com/saurabh_singh/2009/07/02/required-permissions-when-calling-a-web-service-using-client-certificate-for-authentication-in-an-asp-net-web-application/
https://technet.microsoft.com/en-us/library/cc772237(v=ws.10).aspx

Related

Mailkit IMapClient not hitting ServerCertificateValidationCallback & SslHandshakeException

I'm attempting to connect to an IMAP server using the following code on a Windows Server 2019 machine:
using (var client = new ImapClient(new ProtocolLogger("protocol.log")))
{
var address = EnvReader.GetStringValue("EMAIL_ADDRESS");
var password = EnvReader.GetStringValue("EMAIL_PASSWORD");
var creds = new NetworkCredential(address, password);
client.CheckCertificateRevocation = false;
client.ServerCertificateValidationCallback = (s, c, h, e) =>
{
Console.WriteLine("ALL UP IN THIS CALLBACK" + e.ToString());
return true;
};
client.Connect("outlook.office365.com", 993, SecureSocketOptions.SslOnConnect);
client.Authenticate(address, password);
}
On my Mac, this code runs perfectly fine, I can connect and subsequently authenticate just fine.
On the Windows machine I receive the following exception:
MailKit.Security.SslHandshakeException: An error occurred while attempting to establish an SSL or TLS connection.
This usually means that the SSL certificate presented by the server is not trusted by the system for one or more of
the following reasons:
1. The server is using a self-signed certificate which cannot be verified.
2. The local system is missing a Root or Intermediate certificate needed to verify the server's certificate.
3. A Certificate Authority CRL server for one or more of the certificates in the chain is temporarily unavailable.
4. The certificate presented by the server is expired or invalid.
5. The set of SSL/TLS protocols supported by the client and server do not match.
6. You are trying to connect to a port which does not support SSL/TLS.
See https://github.com/jstedfast/MailKit/blob/master/FAQ.md#SslHandshakeException for possible solutions
Based on the info in the linked FAQ, I added the ServerCertificateValidationCallback, however the callback is never hit (The previously mentioned exception is still thrown, the relevant console logging never occurs, and a breakpoint inside the callback is never hit while debugging).
From my reading, the ServerCertificateValidationCallback should handle cases #1-4 that the exception message mentions. The fact that I can connect on the specified port on my Mac would seem to rule out case #6 (I also tried port 143 + SecureSocketOptions.StartTls). That leaves case #5, however, I can't find any information suggesting that Windows Server 2019 can't handle SSL/TSL protocols.
Any ideas for a) dealing with this exception and/or b) figuring out why the ServerCertificateValidationCallback is not firing would be greatly appreciated.
Edit: My project is referencing .NET 5.0
Let's go through each of the possibilities:
The server is using a self-signed certificate which cannot be verified.
outlook.office365.com would not be using a self-signed certificate, so that wouldn't be an issue in this case.
The local system is missing a Root or Intermediate certificate needed to verify the server's certificate.
This one is very possible, but the ServerCertificateValidationCallback override should be overriding this failure. However, it's not getting hit... so it's not actually bypassing this potential error.
A Certificate Authority CRL server for one or more of the certificates in the chain is temporarily unavailable.
This would be negated by client.CheckCertificateRevocation = false;
The certificate presented by the server is expired or invalid.
This is not the case because the certificate does not expire until 1/21/2022.
The set of SSL/TLS protocols supported by the client and server do not match.
The server supports at least TLSv1.2 which is a default TLS protocol version supported by MailKit in all target framework versions (.NET 4.5 -> 5.0 + netstandard2.x's).
You are trying to connect to a port which does not support SSL/TLS.
Port 993 is the correct port and SslOnConnect is the correct option, so this is not the issue.
Assuming there isn't a bug in MailKit's SslStream.AuthenticateAsClientAsync() call that passes in the validation callback method (.NET 5.0 is different than other versions), what is the InnerException? Maybe that will provide some insight.

Could not stablish secure channel for SSL/TLS adding new service reference in Visual Studio

This is the situation: New project (console or forms). I go to References, add new service reference. I write the url and I get an error about that the request is cancelled due to that it can't be stablished a secure channel for SSL/TLS. Without https, it works.
A friend tested in other windows 10 and no problem.
With Iexplorer or chrome, no problem, I see the xml of the wdsl, but with visual studio impossible, it doesn't work. I've tested all the posts that I've seen but nothing. The only way is to generate the proxy class with wdsl.exe
Any idea about this?
Regards.
Do you mean that you fail to invoke the wcf service by adding the service reference when the service is hosted over https?
If the server uses the self-signed certificate as the server identity credential, there is a default step validates the server certificate on the client side. you could refer to the following code.
ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
try
{
var result = client.SayHello();
Console.WriteLine(result);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Feel free to let me know if the problem still exists.
This is because the SSL certificate is not installed in your certificate repository.
Open the web service URL in browser.
It would prompt you to install the SSL CA to your local machine's certificate repository.
The dialog would be showing two options "Local User", "Local Machine".
You MUST select "Local Machine".
Then you should be able to add service reference even using SSL url.
This should solve your issues.

C# app can no longer hit website after they switched to TLS 1.2 - failing on GetResponse()

We have an internal application that makes XML calls out to our vendor sites. For PCI compliance and security reasons, they are starting to disable everything except TLS 1.1 and TLS 1.2. They have set up a test site with this new requirement for us to test against.
Our application (C#, Windows Forms app, .NET 4.5) can connect to their current site just fine.
When I try to make a call to their new test site, it fails on the GetRequestStream() call with "The underlying connection was closed: An unexpected error occurred on a send."
If I update the app and set:
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12
Then it gets by the GetRequestStream() and fails on the GetResponse() call with "The underlying connection was closed: The connection was closed unexpectedly."
I have tried a bunch of stuff, none of which has worked. I am setting the UserAgent, I tried setting KeepAlive = false, ...
If I go to the vendors URL in a browser, I can get to it fine. I am just having issues with my C# app
Any thoughts? I obviously dont have access to their server. Is there a setting someone on my machine I need to change?
I think that it is likely that your request is failing during the TLS negotiation stage. I have had similar problems myself and it usually comes down to having to use a network protocol analyzer (such as wireshark) to trace the communication between the client and server and to determine where the messaging has stopped. If TLS negotiation fails, the server will terminate the connection and you will get errors similar to what you got above.
It may be possible that the test server does not have a proper SSL certificate. You can find out in .NET if there are any SSL validation errors using the ServerCertificateValidationCallback. I suggest to ignore the validation errors when in Debug mode, like this:
#if DEBUG
ServicePointManager.ServerCertificateValidationCallback += ValidationCallback;
#endif
var webRequest = HttpWebRequest.Create("https://your.url");
...
#if DEBUG
bool ValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
}
#endif
This way you knowingly ignore any SSL certificate issues while testing (in Debug mode), but you let the verification mechanism work as usual in production (Release mode). By the way, you can check the sslPolicyErrors parameter to see exactly if and what caused the validation failure.
UPDATE: The author of the question confirmed that the SSL certificate is valid, so my answer doesn't help directly with the error he's receiving.

How to set certificate in C# Win Application

Im using a webservice in my program.
this is the web service : "https://X.Y.Z.W/ib/ws/openbill.asmx?wsdl"
It works as local. when I write this on Internet Explorer, I can see the proper page after selecting "Continue to this website (not recommended)" in this attachment :
but when I want to access to this, in my c# code, I get this exception :
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
So how can I access this in my c# program?
I think you should first acquire a certificate file, and then use it in your code. For example, to set it for a SMTPClient object:
string certificate = "Certificate.cer";
X509Certificate cert = new X509Certificate2(certificate);
MailMessage message = new MailMessage(from, to);
SmtpClient client = new SmtpClient(server);
client.ClientCertificates.Add(cert);
client.Send(message);
The web service that you are trying to connect to is using SSL/TLS. When you open the web service via internet explorer, it is giving you a warning that it cannot validate the certificate of the web service.
This has many reasons, and I guess in your case it is that the certificate that the web service is using is not for X.Y.Z.W.
Another reason could be that your machine does not trust the root issuer of the web service certificate. But from the error message that you have, I don't think this is the case.
You can view the certificate in IE by click on "Continue on this web site..", and the clicking on "Certificate Error", and the "View certificates".
From there, you will view the certificate. Go to details, and look for DNS Name inside Subject Alternative Name.
The DNS name is the name of the machine that the web service certificate was given for.
I guess in your case it will not be X.Y.Z.W.
Is the web service yours? can you obtain a different certificate for it? If so, can make sure you create a certificate that has the correct DNS name.
As a last resort, you can skip certificate validation from your code (this is not recommended). Take a look at this question.

Calling HTTPS JBoss service from C# code throws an authentication error

I'm trying to call a JBoss service from a C# program and I'm getting an annoyingly vague error.
JbossService proxy = new JbossService();
proxy.Credentials = new NetworkCredential("ME", "thepwd");
proxy.Url = //https url snipped
proxy.CookieContainer = new CookieContainer();
proxy.PreAuthenticate = true;
Console.WriteLine("Calling service...");
queryResponse qr = proxy.query();
Console.WriteLine("Done.");
The exception and inner exception thrown are as follows:
exception : The underlying connection was closed: An unexpected error occurred on a send.
inner exception : Authentication failed because the remote party has closed the transport stream.
I'm not quite sure what this means, other than perhaps that JBoss likes me even less than I like it. I'm calling from the local machine so I don't think it's a networking issue. Has anyone seen this before?
This usually happens when your client cannot verify trust over https with the server (usually because the server certificate is self signed or if it is signed by a root authority not installed on your client machine.
Easy fix (although there are security consequences)....somewhere in your initialization code add the following:
System.Net.ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { return true;};
Basically this replaces the application wide handling of server certificate validation and causes your application to accept any certificate. If you want to get finer grained, you can examine the certificate and put some logic in the method.
This works for anything based on System.Net, so it should work for Web Services and any thing based on WebRequest.
I haven't used JBOSS. This is how I troubleshoot similar problems, when using Microsoft technologies -- the same issues may be affecting your program:
Firewall settings or network issue (try connecting manually, to rule this out)
Self-service certificate issues:
Check the following certificate values:
Ensure the server's certificate issuer has a valid, matching issuing trusted root Certificate Authority (CA), on the same machine
The server certificate subject name matches the machine name exactly
The machine name the client is accessing matches that defined in the server certificate
An administrator account set (server) certificate thumbprint
Try recreating the SSL Certificate on both servers)
Try creating your own CA cert, add to trusted publishers, and then create an SSL sert based on that

Categories