David S.
David S.

Reputation: 11200

ServicePointManager.SecurityProtocol is not SecurityProtocolType.SystemDefault

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.

Upvotes: 19

Views: 20339

Answers (4)

richb
richb

Reputation: 4926

Was this problem when debugging in Visual Studio 2015? If so, the answer is likely because you have 'Enable the Visual Studio hosting process' turned on (the default).

The vshost.exe generated by VS 2015 incorrectly has TargetFramework=4.5 set in its metadata. Even though you are running in Framework 4.7, .NET honours the TargetFramework and sets ServicePointManager.SecurityProtocol to Ssl3|Tls.

Your real .exe will have the correct TargetFramework metadata. When you run it SecurityProtocol will be set to SystemDefault.

It's a bug in VS 2015 that never got fixed. You can turn off the VS hosting process in project properties. The vshost process doesn't exist in VS 2017 and later.

Upvotes: 1

Westley
Westley

Reputation: 71

With .NET 4.6 installed you still must put in a registry key to have .NET programs compiled for earlier versions to use strong cryptography. Once this is set, all .NET code will use the newer TLS protocols-

64 bit

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

32 bit

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001

.NET programs compiled for 4.6 framework and higher will act as if the key is there. The ServiceEndpointManager.SecurityProtocol setting can be used to specify it explicitly so it will be used even w/o the registry.

More info: https://learn.microsoft.com/en-us/sharepoint/security-for-sharepoint-server/enable-tls-1-1-and-tls-1-2-support-in-sharepoint-server-2019#34---enable-strong-cryptography-in-net-framework-45-or-higher

Upvotes: 5

Ohad Schneider
Ohad Schneider

Reputation: 38152

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://learn.microsoft.com/en-us/dotnet/framework/network-programming/tls

Upvotes: 12

Doug Dawson
Doug Dawson

Reputation: 1273

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

Upvotes: 1

Related Questions