Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ServicePointManager.SecurityProtocol is not SecurityProtocolType.SystemDefault

Tags:

c#

ssl

I am on Windows 10 1903, and my IE and Chrome can access Tls 1.2 website without any special settings. But when I try to use my .net 4.7.2 application to access a web API which only allows Tls 1.2 connect, my connection got terminated by the server.

I have to add ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; in my code to allow my application to connect to that endpoint correctly.

But after doing some research, I found from this document that for .Net 4.7 and above the default value for ServicePointManager.SecurityProtocol should be SecurityProtocolType.SystemDefault and according to this document the Tls 1.2 protocal is enable by default.

So I traced my code and found that the default value for ServicePointManager.SecurityProtocol on my system is System.Net.SecurityProtocolType.Ssl3 | System.Net.SecurityProtocolType.Tls. What's more crazy, when I set the protocol to SecurityProtocolType.SystemDefault, I got this error:

System.Net.Http.HttpRequestException : An error occurred while sending the request.
---- System.Net.WebException : The underlying connection was closed: An unexpected error occurred on a receive.
-------- System.ArgumentException : The specified value is not valid in the 'SslProtocolType' enumeration.
Parameter name: sslProtocolType

I checked my system registry and IE settings, and nothing overrides or disables Tls 1.2.

So I am very confused and wonder if is there something wrong with my system or with my code.

like image 852
David S. Avatar asked Sep 11 '19 00:09

David S.


2 Answers

You will get this error if the app you're running targets a .NET framework earlier than 4.6 (even if you are actually running it on a newer .NET FX). You can check this by examining the value of AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName.

Specifically, this will get thrown in such a case where the SystemDefaultTlsVersions registry value is not set to 1: https://referencesource.microsoft.com/#System/net/System/Net/SecureProtocols/_SslState.cs,164

AppContext switches won't help you either, as they only take effect for framework versions starting from 4.6. Assuming you can't change the targeted .NET version (example) and you don't want to force your users to change their registry settings, I recommend code like this:

if (ServicePointManager.SecurityProtocol != SecurityProtocolType.SystemDefault)
{
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
}

For more information: https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls

like image 137
Ohad Schneider Avatar answered Oct 14 '22 15:10

Ohad Schneider


We ran into this at the office. My understanding is that the SystemDefault value comes from the Windows registry.

The DefaultSecureProtocols registry entry can be added in the following path:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp
On x64-based computers, DefaultSecureProtocols must also be added to the Wow6432Node path:

HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp
The registry value is a DWORD bitmap. The value to use is determined by adding the values corresponding to the protocols desired.

DefaultSecureProtocols Value    Protocol enabled
0x00000008  Enable SSL 2.0 by default
0x00000020  Enable SSL 3.0 by default
0x00000080  Enable TLS 1.0 by default
0x00000200  Enable TLS 1.1 by default
0x00000800  Enable TLS 1.2 by default

https://support.microsoft.com/en-us/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-default-secure-protocols-in-wi

like image 21
Doug Dawson Avatar answered Oct 14 '22 15:10

Doug Dawson