EWS api - Unable to connect ExchangeServer on-prem - c#

I am implementing the Microsoft EWS api in order to get emails from the on-prem Exchange Server. Considering that the Microsoft has abandoned the development, I am using the sherlock1982 fork from ews api. My app is written in .net core 2.1 and when running on my local PC (win10), everything is working well. Considering that its a Linux, it is not possible to automatically get the Autodiscover url, so I am manually setting it in the code, as suggested on the github page.
public async void GetInbox()
{
string ewsUrl = "https://mail.domain.com/EWS/Exchange.asmx";
try
{
var service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
service.UseDefaultCredentials = false;
// service.Credentials = new NetworkCredential("domainUsername", "password", "domain");
service.Url = new Uri(ewsUrl);
Mailbox mb = new Mailbox("emailAddress");
var cache = new System.Net.CredentialCache();
cache.Add(service.Url, "NTLM", new
System.Net.NetworkCredential("domainUsername", "password",
"domain"));
service.Credentials = cache;
FolderId fid = new FolderId(WellKnownFolderName.Inbox, mb);
Folder inbox = await Folder.Bind(service, fid);
if (inbox != null)
{
_database.LogEvent("LOG", "GetInbox", $"InboxCount: {inbox.TotalCount}");
}
}
catch (Exception e)
{
_database.LogEvent("Error", "GetInbox", $"{e.Message}");
}
}
When deployed to the test server running CentOS7, I am getting following message:
The request failed. The SSL connection could not be established, see inner exception.
at Microsoft.Exchange.WebServices.Data.EwsHttpWebRequest.GetResponse(CancellationToken token) in D:\dev_in_progress\ews-managed-api-master\Core\EwsHttpWebRequest.cs:line 147
at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse(IEwsHttpWebRequest request, CancellationToken token) in D:\dev_in_progress\ews-managed-api-master\Core\Requests\ServiceRequestBase.cs:line 798
--- End of inner exception stack trace ---
at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.GetEwsHttpWebResponse(IEwsHttpWebRequest request, CancellationToken token) in D:\dev_in_progress\ews-managed-api-master\Core\Requests\ServiceRequestBase.cs:line 808
at Microsoft.Exchange.WebServices.Data.ServiceRequestBase.ValidateAndEmitRequest(CancellationToken token) in D:\dev_in_progress\ews-managed-api-master\Core\Requests\ServiceRequestBase.cs:line 688
at Microsoft.Exchange.WebServices.Data.SimpleServiceRequestBase.InternalExecuteAsync(CancellationToken token) in D:\dev_in_progress\ews-managed-api-master\Core\Requests\SimpleServiceRequestBase.cs:line 57
at Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest`1.ExecuteAsync(CancellationToken token) in D:\dev_in_progress\ews-managed-api-master\Core\Requests\MultiResponseServiceRequest.cs:line 134
at Microsoft.Exchange.WebServices.Data.ExchangeService.BindToFolder(FolderId folderId, PropertySet propertySet, CancellationToken token) in D:\dev_in_progress\ews-managed-api-master\Core\ExchangeService.cs:line 325
at Microsoft.Exchange.WebServices.Data.ExchangeService.BindToFolder[TFolder](FolderId folderId, PropertySet propertySet, CancellationToken token) in D:\dev_in_progress\ews-managed-api-master\Core\ExchangeService.cs:line 345
at ExchangeFiles.Email.Download_PI_Files_Email() in D:\dev_in_progress\get_emails_v1\ExchangeFiles\Email.cs:line 199
I have tried ignoring the certificate with
ServicePointManager
.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
but without luck (I am getting the same error).
UPDATE:
I have added a following piece of code
ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) =>
{
if (cert.GetCertHashString().ToLower() == "someHashCert")
{
return true;
}
if (sslPolicyErrors == SslPolicyErrors.None)
{
return true; //Is valid
}
return false;
}
inside the code for creating HttpClientHandler. Its entering inside the if "cert.GetCertHashString().ToLower()" which is good. I have copied the value of someHashCert from the browser.
I also tried setting the
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
But error with this code (and above when checking the cert) is:
The request failed. The handler does not support custom handling of certificates with this combination of libcurl (7.29.0) and its SSL backend ("NSS/3.44"). An SSL backend based on "OpenSSL/1.0.2k-fips" is required. Consider using System.Net.Http.SocketsHttpHandler.
If I set
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", true);
I am getting:
The request failed. GSSAPI operation failed with error - An unsupported mechanism was requested (Unknown error).
I have also tried to setup the callback for certificate from MS doc cert for ews api but then I am getting "Unable to get local issuer certificate" msg.
Not sure is this is step forward or backward... I have a feeling that I have tried everything...
UPDATE2
The ExchangeSever version is 2016, its using NTLM authentification and TLS1.0/1.1
I tried curl -v -k -i --anyauth -u : mail.server.domain:443 and it says
* About to connect() to mail.server.domain: port 443 (#0)
* Trying xx.xx.xx.xxx...
* Connected to mail.server.domain (xx.xx.xx.xxx) port 443 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: mail.server.domain::443
> Accept: */*
Any idea is welcome... Thanks

Unfortunately, nothing suggested from here worked.
I found some comment about similar issue on github and how updating the project to .NET core 3.1 fixed the error, so I decided to give it a try...
It was not a small work, I had several projects inside the solution, but I can confirm that after updating from .NET core 2.1 to .NET core 3.1, everything is working as it should.

Update your TLS on Cent OS.
TLSv1.2 should be available on CentOS 7.
Some documentation.
Linux OpenSSL 1.1.1 supports TLS v1.3 in different Linux OS.
RHEL 8 - Red Hat Enterprise Linux 8 is the first Enterprise Linux distribution that ships with the TLS v1.3 protocol fully integrated into the operating system.
Older CentOS and RHEL OS versions have OpenSSL v1.0.2 installed by default, so TLS v1.3 is not supported natively.
OpenSSL can be yum updated to OpenSSL v1.1.1 to support TLS v1.3.
Blockquote
How to install OpenSSL v1.1.1 on CentOS RedHat Linux:
Use the OpenSSL Version Command to verify the OpenSSL Version:
openssl version
Install wget(If it is not installed):
yum install wget
Download the latest version using wget:
wget https://ftp.openssl.org/source/old/1.1.1/openssl-1.1.1.tar.gz
Decompress the file:
tar xvf openssl-1.1.1.tar.gz
Further configuration is necessary, Please consult your System Administrators prior to making any changes.
disabled by default system wide. If you enable TLS v1.3 on a system for testing, then
TLS should be supported by OS and .net framework.
Check OS and upgrade it if it does not support TLS 1.2
then use Right .net framework which supports TLS 1.2 /1.3
Install Self signed cert on Cent OS also.
Will TLS 1.3 be supported on .NET?
For .NET, the official guidance at this point (via the best practices page above) is to rely on the underlying OS to provide the TLS version (which will automatically default to the strongest available version of the TLS protocol), and avoid hardcoding/specifying an explicit TLS version in application code.
Starting with .NET Framework 4.7, the default configuration is to use the OS TLS version.
Other links which may be helpful: https://github.com/dotnet/docs/issues/4675 and https://learn.microsoft.com/en-us/dotnet/framework/network-programming/tls

Related

Azure Cognitive Speech TTS API does not work on Windows 8, 8.1, Server 2012, Server 2012R2 since 2022-01

I found an issue of Azure Cognitive Speech TTS Service;
Azure Cognitive Speech TTS API does not work on Windows 8,/8.1/Server 2012/Server2012R2 since 2022-01.
I made a program with Microsoft Cognitive Services Speech SDK and it worked well on Windows 8/8.1/Server2012/Server2012R2 as well as Windows 10/Server 2019.
I confirmed that there were logs that it has worked correctly until 2021-11-30 at least.
However, it does not work today.
So, I made a simple sample with Microsoft.CognitiveServices.Speech.csharp nuget package.
My sample code is as the following;
public static async Task SynthesisToAudioFileAsync(string text, string outputFileName)
{
var config = SpeechConfig.FromSubscription("xxxxx", "westus2");
config.SpeechSynthesisLanguage = "ko-KR";
config.SetSpeechSynthesisOutputFormat(SpeechSynthesisOutputFormat.Audio24Khz48KBitRateMonoMp3);
config.SpeechSynthesisVoiceName = "ko-KR-SunHiNeural";
using (var fileOutput = AudioConfig.FromWavFileOutput(outputFileName))
{
using (var synthesizer = new SpeechSynthesizer(config, fileOutput))
{
var result = await synthesizer.SpeakTextAsync(text);
if (result.Reason == ResultReason.SynthesizingAudioCompleted)
{
Console.WriteLine($"Speech synthesized to [{outputFileName}]");
}
else if (result.Reason == ResultReason.Canceled)
{
var cancellation = SpeechSynthesisCancellationDetails.FromResult(result);
Console.WriteLine($"CANCELED: Reason={cancellation.Reason}");
if (cancellation.Reason == CancellationReason.Error)
{
Console.WriteLine($"CANCELED: ErrorCode={cancellation.ErrorCode}");
Console.WriteLine($"CANCELED: ErrorDetails=[{cancellation.ErrorDetails}]");
Console.WriteLine($"CANCELED: Did you update the subscription info?");
}
}
else
{
Console.Write(result.Reason.ToString());
}
}
}
}
It works well on Windows 10/Server2019 with no error.
However, it does not work on Windows 8,/8.1/Server 2012/Server2012R2.
Of course, I executed windows update fully.
The error message is as the following;
CANCELED: Reason=Error
CANCELED: ErrorCode=ConnectionFailure
CANCELED: ErrorDetails=[Connection failed (no connection to the remote host). In
ternal error: 11. Error details: Code: 0. USP state: 2. Received audio size: 0 b
ytes.]
CANCELED: Did you update the subscription info?
I suspect that it may be TLS 1.2 issue and tried as the followings;
I changed Microsoft.CognitiveServices.Speech.csharp nuget package to several versions - 1.14, 1.13 and 1.19(latest version) but it did not work.
I tried to enable TLS 1.2 on Windows 8.1/Server2012 according to many google search results;
https://github.com/MicrosoftDocs/memdocs/blob/main/memdocs/configmgr/core/plan-design/security/includes/update-net-framework-to-support-tls-1-2.md
https://hide.me/en/knowledgebase/how-to-enable-tls-1-1-tls-1-2-in-windows-7-and-8/
https://learn.microsoft.com/en-us/mem/configmgr/core/plan-design/security/enable-tls-1-2-client
and other many postings.
But, it did not work.
I downloaded Cognitive-Speech-TTS sample (Cognitive-Speech-TTS-master.zip) and run C# sample in Old folder.
https://github.com/Azure-Samples/Cognitive-Speech-TTS
It does not use Azure SDK and implements https rest API in low level. So I can review and change codes.
It also worked on Windows 10 but did not work on Windows 81./Server2012 as the following error message;
Starting TTSSample request code execution.
Unhandled Exception: System.AggregateException: One or more errors occurred. --->
System.Net.Http.HttpRequestException: An error occurred while sending the request. --->
System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel.
at System.Net.HttpWebRequest.EndGetRequestStream(IAsyncResult asyncResult, TransportContext& context)
at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
I confirmed that token API (https://westus2.api.cognitive.microsoft.com/sts/v1.0/issueToken) was called well but speak API (https://westus2.tts.speech.microsoft.com/cognitiveservices/v1) was not called with error message.
According to error message, it seems to TLS 1.2 issue.
So, I added to the following line;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11;
The error message became changed as the following on Windows 10 as well as Windows 8.1/Server2012
Starting Authtentication
Unhandled Exception: System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. --->
System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host --->
System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
It was expected behavior because I forced TLS 1.1.
However, the error occurred in authentication step, contrary to above result - above test passed authentication.
So, TLS 1.2 may be enabled on my Windows 81./server2012 because token Uri may require TLS 1.2 according to above testing result.
I tired with speech recognition C# sample in cognitive-services-speech-sdk-master.
https://github.com/Azure-Samples/cognitive-services-speech-sdk
It worked well Windows 81./Server2012 as well as Windows 10.
MS doc said that Azure Cognitive Service requires TLS 1.2.
If TLS 1.2 is not available on my Windows 8.1/Server2012, all Azure Cognitive Service API must fail.
However, only TTS API fails.
Beside, it has worked until 2021-11 at least.
I've tried almost everything I could, but failed.
Finally I suspect that there may be some changes in Azure Cognitive TTS system at the end of 2021 and it may make the issue related to TLS connection from Windows 8/8.1/Server2012/Server2012R2.
In fact, the issue was reported on my customer's machines and upgrading Windows OS to Windows10/Server2019 is not an option because of many reasons.
So, I have to find a workaround on Windows 8/8.1/Server2012/Server2012R2.
Could you please let me know how I can solve the issue?
Best regards.
P.S.
I captured network packets of Cognitive-Speech-TTS C# sample using WireShark and confirmed that TLS 1.2 was used.
First handshaking to retrieve token(westus2.api.cognitive.microsoft.com - 20.51.8.244) succeeded but second handshaking to Azure Cognitive TTS Service(westus2.tts.speech.microsoft.com - 20.51.12.193) failed with the following message;
TLSv1.2 Record Layer: Handshake Protocol: Client Hello
TLSv1.2 Record Layer: Alert (Level: Fatal, Description: Handshake Failure).
I tested on Windows 10 and all TLS 1.2 handshaking succeeded with same test console program.
I added the following code to ignore certificate validation but it did not work;
ServicePointManager.ServerCertificateValidationCallback += (object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors) =>
{
return true;
};
I found actual reason.
It was TLS cipher suite issue of Azure TTS Service API Server.
I executed sslscan to westus2.tts.speech.microsoft.com and the result was as the following;
westus2.tts.speech.microsoft.com
Preferred TLSv1.2 128 bits ECDHE-RSA-AES128-GCM-SHA256 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits ECDHE-RSA-AES256-GCM-SHA384 Curve 25519 DHE 253
Accepted TLSv1.2 256 bits ECDHE-RSA-CHACHA20-POLY1305 Curve 25519 DHE 253
I compared packet capturing result of WireShark between Windows 8.1 and Windows 10.
The result of Windows 10 has ECDHE-RSA-AES128-GCM-SHA256 and ECDHE-RSA-AES256-GCM-SHA384 but the result of Windows 8.1 does not.
So, Azure TTS API cannot work on Windows8/8.1/Server2012/Server2012R2 and it must be fixed by MS.

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.

The request was aborted: Could not create SSL/TLS secure channel on host, local run fine [duplicate]

We are unable to connect to an HTTPS server using WebRequest because of this error message:
The request was aborted: Could not create SSL/TLS secure channel.
We know that the server doesn't have a valid HTTPS certificate with the path used, but to bypass this issue, we use the following code that we've taken from another StackOverflow post:
private void Somewhere() {
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AlwaysGoodCertificate);
}
private static bool AlwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) {
return true;
}
The problem is that server never validates the certificate and fails with the above error. Does anyone have any idea of what I should do?
I should mention that a colleague and I performed tests a few weeks ago and it was working fine with something similar to what I wrote above. The only "major difference" we've found is that I'm using Windows 7 and he was using Windows XP. Does that change something?
I finally found the answer (I haven't noted my source but it was from a search);
While the code works in Windows XP, in Windows 7, you must add this at the beginning:
// using System.Net;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// Use SecurityProtocolType.Ssl3 if needed for compatibility reasons
And now, it works perfectly.
ADDENDUM
As mentioned by Robin French; if you are getting this problem while configuring PayPal, please note that they won't support SSL3 starting by December, 3rd 2018. You'll need to use TLS. Here's Paypal page about it.
The solution to this, in .NET 4.5 is
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
If you don’t have .NET 4.5 then use
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
Make sure the ServicePointManager settings are made before the HttpWebRequest is created, else it will not work.
Works:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")
Fails:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://google.com/api/")
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
Note: Several of the highest voted answers here advise setting ServicePointManager.SecurityProtocol, but Microsoft explicitly advises against doing that. Below, I go into the typical cause of this issue and the best practices for resolving it.
One of the biggest causes of this issue is the active .NET Framework version. The .NET framework runtime version affects which security protocols are enabled by default.
In ASP.NET sites, the framework runtime version is often specified in web.config. (see below)
In other apps, the runtime version is usually the version for which the project was built, regardless of whether it is running on a machine with a newer .NET version.
There doesn't seem to be any authoritative documentation on how it specifically works in different versions, but it seems the defaults are determined more or less as follows:
Framework Version
Default Protocols
4.5 and earlier
SSL 3.0, TLS 1.0
4.6.x
TLS 1.0, 1.1, 1.2, 1.3
4.7+
System (OS) Defaults
For the older versions, your mileage may vary somewhat based on which .NET runtimes are installed on the system. For example, there could be a situation where you are using a very old framework and TLS 1.0 is not supported, or using 4.6.x and TLS 1.3 is not supported.
Microsoft's documentation strongly advises using 4.7+ and the system defaults:
We recommend that you:
Target .NET Framework 4.7 or later versions on your apps. Target .NET Framework 4.7.1 or later versions on your WCF apps.
Do not specify the TLS version. Configure your code to let the OS decide on the TLS version.
Perform a thorough code audit to verify you're not specifying a TLS or SSL version.
For ASP.NET sites: check the targetFramework version in your <httpRuntime> element, as this (when present) determines which runtime is actually used by your site:
<httpRuntime targetFramework="4.5" />
Better:
<httpRuntime targetFramework="4.7" />
I had this problem trying to hit https://ct.mob0.com/Styles/Fun.png, which is an image distributed by CloudFlare on its CDN that supports crazy stuff like SPDY and weird redirect SSL certs.
Instead of specifying Ssl3 as in Simons answer I was able to fix it by going down to Tls12 like this:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
new WebClient().DownloadData("https://ct.mob0.com/Styles/Fun.png");
The problem you're having is that the aspNet user doesn't have access to the certificate. You have to give access using the winhttpcertcfg.exe
An example on how to set this up is at:
http://support.microsoft.com/kb/901183
Under step 2 in more information
EDIT: In more recent versions of IIS, this feature is built in to the certificate manager tool - and can be accessed by right clicking on the certificate and using the option for managing private keys. More details here: https://serverfault.com/questions/131046/how-to-grant-iis-7-5-access-to-a-certificate-in-certificate-store/132791#132791
After many long hours with this same issue I found that the ASP.NET account the client service was running under didn't have access to the certificate. I fixed it by going into the IIS Application Pool that the web app runs under, going into Advanced Settings, and changing the Identity to the LocalSystem account from NetworkService.
A better solution is to get the certificate working with the default NetworkService account but this works for quick functional testing.
The error is generic and there are many reasons why the SSL/TLS negotiation may fail. The most common is an invalid or expired server certificate, and you took care of that by providing your own server certificate validation hook, but is not necessarily the only reason. The server may require mutual authentication, it may be configured with a suites of ciphers not supported by your client, it may have a time drift too big for the handshake to succeed and many more reasons.
The best solution is to use the SChannel troubleshooting tools set. SChannel is the SSPI provider responsible for SSL and TLS and your client will use it for the handshake. Take a look at TLS/SSL Tools and Settings.
Also see How to enable Schannel event logging.
The approach with setting
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Seems to be okay, because Tls1.2 is latest version of secure protocol. But I decided to look deeper and answer do we really need to hardcode it.
Specs: Windows Server 2012R2 x64.
From the internet there is told that .NetFramework 4.6+ must use Tls1.2 by default. But when I updated my project to 4.6 nothing happened.
I have found some info that tells I need manually do some changes to enable Tls1.2 by default
https://support.microsoft.com/en-in/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-default-secure-protocols-in-wi
But proposed windows update doesnt work for R2 version
But what helped me is adding 2 values to registry. You can use next PS script so they will be added automatically
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
That is kind of what I was looking for. But still I cant answer on question why NetFramework 4.6+ doesn't set this ...Protocol value automatically?
Another possible cause of the The request was aborted: Could not create SSL/TLS secure channel error is a mismatch between your client PC's configured cipher_suites values, and the values that the server is configured as being willing and able to accept. In this case, when your client sends the list of cipher_suites values that it is able to accept in its initial SSL handshaking/negotiation "Client Hello" message, the server sees that none of the provided values are acceptable, and may return an "Alert" response instead of proceeding to the "Server Hello" step of the SSL handshake.
To investigate this possibility, you can download Microsoft Message Analyzer, and use it to run a trace on the SSL negotiation that occurs when you try and fail to establish an HTTPS connection to the server (in your C# app).
If you are able to make a successful HTTPS connection from another environment (e.g. the Windows XP machine that you mentioned -- or possibly by hitting the HTTPS URL in a non-Microsoft browser that doesn't use the OS's cipher suite settings, such as Chrome or Firefox), run another Message Analyzer trace in that environment to capture what happens when the SSL negotiation succeeds.
Hopefully, you'll see some difference between the two Client Hello messages that will allow you to pinpoint exactly what about the failing SSL negotiation is causing it to fail. Then you should be able to make configuration changes to Windows that will allow it to succeed. IISCrypto is a great tool to use for this (even for client PCs, despite the "IIS" name).
The following two Windows registry keys govern the cipher_suites values that your PC will use:
HKLM\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002
HKLM\SYSTEM\CurrentControlSet\Control\Cryptography\Configuration\Local\SSL\00010002
Here's a full writeup of how I investigated and solved an instance of this variety of the Could not create SSL/TLS secure channel problem: http://blog.jonschneider.com/2016/08/fix-ssl-handshaking-error-in-windows.html
Something the original answer didn't have. I added some more code to make it bullet proof.
ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;
The top-voted answer will probably be enough for most people. However, in some circumstances, you could continue getting a "Could not create SSL/TLS secure channel" error even after forcing TLS 1.2. If so, you may want to consult this helpful article for additional troubleshooting steps. To summarize: independent of the TLS/SSL version issue, the client and server must agree on a "cipher suite." During the "handshake" phase of the SSL connection, the client will list its supported cipher-suites for the server to check against its own list. But on some Windows machines, certain common cipher-suites may have been disabled (seemingly due to well-intentioned attempts to limit attack surface), decreasing the possibility of the client & server agreeing on a cipher suite. If they cannot agree, then you may see "fatal alert code 40" in the event viewer and "Could not create SSL/TLS secure channel" in your .NET program.
The aforementioned article explains how to list all of a machine's potentially-supported cipher suites and enable additional cipher suites through the Windows Registry. To help check which cipher suites are enabled on the client, try visiting this diagnostic page in MSIE. (Using System.Net tracing may give more definitive results.) To check which cipher suites are supported by the server, try this online tool (assuming that the server is Internet-accessible). It should go without saying that Registry edits must be done with caution, especially where networking is involved. (Is your machine a remote-hosted VM? If you were to break networking, would the VM be accessible at all?)
In my company's case, we enabled several additional "ECDHE_ECDSA" suites via Registry edit, to fix an immediate problem and guard against future problems. But if you cannot (or will not) edit the Registry, then numerous workarounds (not necessarily pretty) come to mind. For example: your .NET program could delegate its SSL traffic to a separate Python program (which may itself work, for the same reason that Chrome requests may succeed where MSIE requests fail on an affected machine).
This one is working for me in MVC webclient
public string DownloadSite(string RefinedLink)
{
try
{
Uri address = new Uri(RefinedLink);
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
using (WebClient webClient = new WebClient())
{
var stream = webClient.OpenRead(address);
using (StreamReader sr = new StreamReader(stream))
{
var page = sr.ReadToEnd();
return page;
}
}
}
catch (Exception e)
{
log.Error("DownloadSite - error Lin = " + RefinedLink, e);
return null;
}
}
"The request was aborted: Could not create SSL/TLS secure channel" exception can occur if the server is returning an HTTP 401 Unauthorized response to the HTTP request.
You can determine if this is happening by turning on trace-level System.Net logging for your client application, as described in this answer.
Once that logging configuration is in place, run the application and reproduce the error, then look in the logging output for a line like this:
System.Net Information: 0 : [9840] Connection#62912200 - Received status line: Version=1.1, StatusCode=401, StatusDescription=Unauthorized.
In my situation, I was failing to set a particular cookie that the server was expecting, leading to the server responding to the request with the 401 error, which in turn led to the "Could not create SSL/TLS secure channel" exception.
Another possibility is improper certificate importation on the box. Make sure to select encircled check box. Initially I didn't do it, so code was either timing out or throwing same exception as private key could not be located.
I had this problem because my web.config had:
<httpRuntime targetFramework="4.5.2" />
and not:
<httpRuntime targetFramework="4.6.1" />
Doing this helped me:
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Finally found solution for me.
Try this adding below line before calling https url (for .Net framework 4.5):
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
As you can tell there are plenty of reasons this might happen. Thought I would add the cause I encountered ...
If you set the value of WebRequest.Timeout to 0, this is the exception that is thrown. Below is the code I had... (Except instead of a hard-coded 0 for the timeout value, I had a parameter which was inadvertently set to 0).
WebRequest webRequest = WebRequest.Create(#"https://myservice/path");
webRequest.ContentType = "text/html";
webRequest.Method = "POST";
string body = "...";
byte[] bytes = Encoding.ASCII.GetBytes(body);
webRequest.ContentLength = bytes.Length;
var os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
os.Close();
webRequest.Timeout = 0; //setting the timeout to 0 causes the request to fail
WebResponse webResponse = webRequest.GetResponse(); //Exception thrown here ...
The root of this exception in my case was that at some point in code the following was being called:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
This is really bad. Not only is it instructing .NET to use an insecure protocol, but this impacts every new WebClient (and similar) request made afterward within your appdomain. (Note that incoming web requests are unaffected in your ASP.NET app, but new WebClient requests, such as to talk to an external web service, are).
In my case, it was not actually needed, so I could just delete the statement and all my other web requests started working fine again. Based on my reading elsewhere, I learned a few things:
This is a global setting in your appdomain, and if you have concurrent activity, you can't reliably set it to one value, do your action, and then set it back. Another action may take place during that small window and be impacted.
The correct setting is to leave it default. This allows .NET to continue to use whatever is the most secure default value as time goes on and you upgrade frameworks. Setting it to TLS12 (which is the most secure as of this writing) will work now but in 5 years may start causing mysterious problems.
If you really need to set a value, you should consider doing it in a separate specialized application or appdomain and find a way to talk between it and your main pool. Because it's a single global value, trying to manage it within a busy app pool will only lead to trouble. This answer: https://stackoverflow.com/a/26754917/7656 provides a possible solution by way of a custom proxy. (Note I have not personally implemented it.)
In my case, the service account running the application did not have permission to access the private key. Once I gave this permission, the error went away
mmc
certificates
Expand to personal
select cert
right click
All tasks
Manage private keys
Add the service account user
If you are running your code from Visual Studio, try running Visual Studio as administrator. Fixed the issue for me.
System.Net.WebException: The request was aborted: Could not create
SSL/TLS secure channel.
In our case, we where using a software vendor so we didn't have access to modify the .NET code. Apparently .NET 4 won't use TLS v 1.2 unless there is a change.
The fix for us was adding the SchUseStrongCrypto key to the registry. You can copy/paste the below code into a text file with the .reg extension and execute it. It served as our "patch" to the problem.
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
I have struggled with this problem all day.
When I created a new project with .NET 4.5 I finally got it to work.
But if I downgraded to 4.0 I got the same problem again, and it was irreversable for that project (even when i tried to upgrade to 4.5 again).
Strange no other error message but "The request was aborted: Could not create SSL/TLS secure channel." came up for this error
In case that the client is a windows machine, a possible reason could be that the tls or ssl protocol required by the service is not activated.
This can be set in:
Control Panel -> Network and Internet -> Internet Options -> Advanced
Scroll settings down to "Security" and choose between
Use SSL 2.0
Use SSL 3.0
Use TLS 1.0
Use TLS 1.1
Use TLS 1.2
none of this answer not working for me , the google chrome and postman work and handshake the server but ie and .net not working. in google chrome in security tab > connection show that encrypted and authenticated using ECDHE_RSA with P-256 and AES_256_GCM cipher suite to handshake with the server.
i install IIS Crypto and in cipher suites list on windows server 2012 R2 ican't find ECDHE_RSA with P-256 and AES_256_GCM cipher suite. then i update windows to the last version but the problem not solve. finally after searches i understood that windows server 2012 R2 not support GSM correctly and update my server to windows server 2016 and my problem solved.
I was having this same issue and found this answer worked properly for me. The key is 3072. This link provides the details on the '3072' fix.
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
XmlReader r = XmlReader.Create(url);
SyndicationFeed albums = SyndicationFeed.Load(r);
In my case two feeds required the fix:
https://www.fbi.gov/feeds/fbi-in-the-news/atom.xml
https://www.wired.com/feed/category/gear/latest/rss
None of the answers worked for me.
This is what worked:
Instead of initializing my X509Certifiacte2 like this:
var certificate = new X509Certificate2(bytes, pass);
I did it like this:
var certificate = new X509Certificate2(bytes, pass, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);
Notice the X509KeyStorageFlags.Exportable !!
I didn't change the rest of the code (the WebRequest itself):
// I'm not even sure the first two lines are necessary:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
request = (HttpWebRequest)WebRequest.Create(string.Format("https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", server));
request.Method = "GET";
request.Referer = string.Format("https://hercules.sii.cl/cgi_AUT2000/autInicio.cgi?referencia=https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", servidor);
request.UserAgent = "Mozilla/4.0";
request.ClientCertificates.Add(certificate);
request.CookieContainer = new CookieContainer();
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
// etc...
}
In fact I'm not even sure that the first two lines are necessary...
Another possibility is that the code being executed doesn't have the required permissions.
In my case, I got this error when using Visual Studio debugger to test a call to a web service. Visual Studio wasn't running as Administrator, which caused this exception.
This fixed for me, add Network Service to permissions.
Right click on the certificate > All Tasks > Manage Private Keys... > Add... > Add "Network Service".

RabbitMQ .NET Client Not Working with TLS v1.2

Trying to get RabbitMQ wired up to play nice with TLS v1.2. Working with both a Java client and a .NET Core client. The Java client is working but the .NET one is pushing back. Here are my factory settings:
var factory = new ConnectionFactory
{
HostName = hostName,
VirtualHost = vHost,
UserName = username,
Password = password,
Port = 5671,
Ssl = {Enabled = true}
};
I’m getting this exception:
System.Security.Authentication.AuthenticationException: A call to SSPI failed, see inner exception.
---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.
---> Interop+Crypto+OpenSslCryptographicException: error:1409442E:SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version
Looking at the very tail end of the exception message it appears that the TLS version might be old but I have the latest version of RabbitMQ installed – 4.1.1
Dug into the RabbitMQ source for the ConnectionFactory class but cannot find anything relating to setting the TLS version. In my Java app it works thusly: factory.useSslProtocol("TLSv1.2");
Saw in another SO thread that an old version of Erlang might be the cause but I have the latest version (8.1) installed.
Any pointers on where to look next?
UPDATE: Foound the way to set the TLS property:
factory.Ssl.Version = SslProtocols.Tls12;
But now I'm getting a System.Security.Authentication.AuthenticationException: The remote certificate is invalid exception.
this worked for me:
Ssl = new SslOption
{
Version = SslProtocols.Tls12,
Enabled = true,
}

RestSharp: Could not create SSL/TLS secure channel

I'm trying to use RestSharp in Visual Studio 2012 Express on a fresh install of Windows 8.1. The API I'm trying to use supports only RC4-SHA for SSL. The certificate is valid.
var client = new RestClient();
client.BaseUrl = "https://teststore.mybigcommerce.com/api/v2/";
client.Authenticator = new HttpBasicAuthenticator("username", "key");
var request = new RestRequest();
request.Resource = "time.json";
IRestResponse response = client.Execute(bcrequest);
I keep getting an error from the client: The request was aborted: Could not create SSL/TLS secure channel. I thought there were certificate problems, until I finally took a packet capture and discovered there were no cipher suites in common. RC4-SHA is not available on the client end. After installing Windows 7 and running the exact same code, the problem goes away.
Why is RC4-SHA unavailable in RestSharp on Windows 8.1?
I always add the following line of code before making the initial network connection to solve this issue.
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls11 | System.Net.SecurityProtocolType.Tls11;
I had an application the failed tls handshake after I insalled Win 8.1. My Wireshark captures on working and non working client logons showed missing cipher suites. Installing a real certificate on the server I was connecting to also solved the problem. The server had a self signed certificate.
I finally found this Microsoft article:
RC4 is no longer enabled by default for TLS. Applications (such as
Internet Explorer) might fail to connect if they depend on RC4
You can enable RC4 support by configuring these registry keys with the
following REG command:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers]
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4
128/128]"Enabled"=dword:ffffffff
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4
40/128]"Enabled"=dword:ffffffff
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4
56/128]"Enabled"=dword:ffffffff

Categories