|
2 | 2 | using System.Globalization;
|
3 | 3 | using System.IO;
|
4 | 4 | using System.Linq;
|
5 |
| -using System.Net.Security; |
| 5 | +using System.Net; |
| 6 | +#if NETSTANDARD1_3 || NETSTANDARD2_0 |
6 | 7 | using System.Runtime.InteropServices;
|
| 8 | +#endif |
| 9 | +#if NET45 || NET46 |
| 10 | +using System.Reflection; |
| 11 | +#endif |
7 | 12 | using System.Security.Authentication;
|
8 | 13 | using System.Security.Cryptography;
|
9 | 14 | using System.Text;
|
@@ -262,27 +267,26 @@ public static SslProtocols GetDefaultSslProtocols()
|
262 | 267 | {
|
263 | 268 | if (!s_defaultSslProtocols.HasValue)
|
264 | 269 | {
|
| 270 | + // Prior to .NET Framework 4.7, SslProtocols.None is not a valid argument to SslStream.AuthenticateAsClientAsync. |
| 271 | + // If the NET46 build is loaded by an application that targets. NET 4.7 (or later), or if app.config has set |
| 272 | + // Switch.System.Net.DontEnableSystemDefaultTlsVersions to false, then SslProtocols.None will work; otherwise, |
| 273 | + // if the application targets .NET 4.6.2 or earlier and hasn't changed the AppContext switch, then it will |
| 274 | + // fail at runtime. We attempt to determine if it will fail by accessing the internal static |
| 275 | + // ServicePointManager.DisableSystemDefaultTlsVersions property, which controls whether SslProtocols.None is |
| 276 | + // an acceptable value. |
| 277 | + bool disableSystemDefaultTlsVersions; |
265 | 278 | try
|
266 | 279 | {
|
267 |
| - using (var memoryStream = new MemoryStream()) |
268 |
| - using (var sslStream = new SslStream(memoryStream)) |
269 |
| - { |
270 |
| - sslStream.AuthenticateAsClient("localhost", null, SslProtocols.None, false); |
271 |
| - } |
272 |
| - } |
273 |
| - catch (ArgumentException ex) when (ex.ParamName == "sslProtocolType") |
274 |
| - { |
275 |
| - // Prior to .NET Framework 4.7, SslProtocols.None is not a valid argument to AuthenticateAsClientAsync. |
276 |
| - // If the NET46 build is loaded by an application that targets. NET 4.7 (or later), or if app.config has set |
277 |
| - // Switch.System.Net.DontEnableSystemDefaultTlsVersions to false, then SslProtocols.None will work; otherwise, |
278 |
| - // if the application targets .NET 4.6.2 or earlier and hasn't changed the AppContext switch, then it will |
279 |
| - // fail at runtime; we catch the exception and explicitly specify the protocols to use. |
280 |
| - s_defaultSslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12; |
| 280 | + var property = typeof(ServicePointManager).GetProperty("DisableSystemDefaultTlsVersions", BindingFlags.NonPublic | BindingFlags.Static); |
| 281 | + disableSystemDefaultTlsVersions = property == null || (property.GetValue(null) is bool b && b); |
281 | 282 | }
|
282 | 283 | catch (Exception)
|
283 | 284 | {
|
284 |
| - s_defaultSslProtocols = SslProtocols.None; |
| 285 | + // couldn't access the property; assume the safer default of 'true' |
| 286 | + disableSystemDefaultTlsVersions = true; |
285 | 287 | }
|
| 288 | + |
| 289 | + s_defaultSslProtocols = disableSystemDefaultTlsVersions ? (SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12) : SslProtocols.None; |
286 | 290 | }
|
287 | 291 |
|
288 | 292 | return s_defaultSslProtocols.Value;
|
|
0 commit comments