Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ internal static partial class WinHttp
public const uint WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 = 0x00000080;
public const uint WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 = 0x00000200;
public const uint WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 = 0x00000800;
public const uint WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 = 0x00002000;

public const uint SECURITY_FLAG_IGNORE_UNKNOWN_CA = 0x00000100;
public const uint SECURITY_FLAG_IGNORE_CERT_DATE_INVALID = 0x00002000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public async Task GetAsync_AllowedSSLVersion_Succeeds(SslProtocols acceptedProto
#if !NETFRAMEWORK
handler.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13;
#else
handler.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
handler.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | (SslProtocols)12288;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
handler.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | (SslProtocols)12288;
handler.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | (SslProtocols)0x3000;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the reason for 12288 is that's what we use in the definition:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that is rather ugly. I wonder why? Perhaps it was auto-generated at some point?
I would still consider that hex values are more developer-friendly for reading ...

BTW: Definition is technically hex-defined:


public const int SP_PROT_TLS1_3_SERVER = 0x00001000;
public const int SP_PROT_TLS1_3_CLIENT = 0x00002000;
public const int SP_PROT_TLS1_3 = (SP_PROT_TLS1_3_SERVER | SP_PROT_TLS1_3_CLIENT);

#endif
#pragma warning restore 0618
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public class WinHttpHandler : HttpMessageHandler

private static readonly StringWithQualityHeaderValue s_gzipHeaderValue = new StringWithQualityHeaderValue("gzip");
private static readonly StringWithQualityHeaderValue s_deflateHeaderValue = new StringWithQualityHeaderValue("deflate");
private static readonly Lazy<bool> s_supportsTls13 = new Lazy<bool>(CheckTls13Support());

[ThreadStatic]
private static StringBuilder? t_requestHeadersBuilder;
Expand Down Expand Up @@ -1156,6 +1157,7 @@ private void SetSessionHandleConnectionOptions(SafeWinHttpHandle sessionHandle)

private void SetSessionHandleTlsOptions(SafeWinHttpHandle sessionHandle)
{
const SslProtocols Tls13 = (SslProtocols)12288; // enum is missing in .NET Standard
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const SslProtocols Tls13 = (SslProtocols)12288; // enum is missing in .NET Standard
const SslProtocols Tls13 = (SslProtocols)0x3000; // enum is missing in .NET Standard

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took the value from documentation. But I don't really care. It seems like the SP_PROT is platform specific mapping that happens to be the same on Windows.
It feels like this is really matter of personal preference.

uint optionData = 0;
SslProtocols sslProtocols =
(_sslProtocols == SslProtocols.None) ? SecurityProtocol.DefaultSecurityProtocols : _sslProtocols;
Expand Down Expand Up @@ -1187,10 +1189,13 @@ private void SetSessionHandleTlsOptions(SafeWinHttpHandle sessionHandle)
optionData |= Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
}

// As of Win10RS5 there's no public constant for WinHTTP + TLS 1.3
// This library builds against netstandard, which doesn't define the Tls13 enum field.
// Set this only if supported by WinHttp version.
if (s_supportsTls13.Value && (sslProtocols & Tls13) != 0)
{
optionData |= Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3;
}

// If only unknown values (e.g. TLS 1.3) were asked for, report ERROR_INVALID_PARAMETER.
// If only unknown values were asked for, report ERROR_INVALID_PARAMETER.
if (optionData == 0)
{
throw WinHttpException.CreateExceptionUsingError(
Expand All @@ -1201,6 +1206,30 @@ private void SetSessionHandleTlsOptions(SafeWinHttpHandle sessionHandle)
SetWinHttpOption(sessionHandle, Interop.WinHttp.WINHTTP_OPTION_SECURE_PROTOCOLS, ref optionData);
}

private static bool CheckTls13Support()
{
try
{
using (var handler = new WinHttpHandler())
using (SafeWinHttpHandle sessionHandle = Interop.WinHttp.WinHttpOpen(
IntPtr.Zero,
Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY,
Interop.WinHttp.WINHTTP_NO_PROXY_NAME,
Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS,
(int)Interop.WinHttp.WINHTTP_FLAG_ASYNC))
{
uint optionData = Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3;

handler.SetWinHttpOption(sessionHandle, Interop.WinHttp.WINHTTP_OPTION_SECURE_PROTOCOLS, ref optionData);
return true;
}
}
catch
{
return false;
}
}

private void SetSessionHandleTimeoutOptions(SafeWinHttpHandle sessionHandle)
{
if (!Interop.WinHttp.WinHttpSetTimeouts(
Expand Down