Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update SSL tests to deal better with disabled protocols #65120

Merged
merged 15 commits into from
Feb 17, 2022
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
4 changes: 3 additions & 1 deletion src/libraries/Common/tests/System/Net/SslProtocolSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,12 @@ public IEnumerator<object[]> GetEnumerator()
{
foreach (SslProtocols protocol in Enum.GetValues(typeof(SslProtocols)))
{
if (protocol != SslProtocols.None && (protocol & SupportedSslProtocols) == protocol)
#pragma warning disable 0618 // SSL2/3 are deprecated
if (protocol != SslProtocols.None && protocol != SslProtocols.Default && (protocol & SupportedSslProtocols) == protocol)
{
yield return new object[] { protocol };
}
#pragma warning restore 0618
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,16 +140,23 @@ public static SecurityStatusPal Renegotiate(

public static SafeFreeCredentials AcquireCredentialsHandle(SslStreamCertificateContext? certificateContext, SslProtocols protocols, EncryptionPolicy policy, bool isServer)
{
// New crypto API supports TLS1.3 but it does not allow to force NULL encryption.
SafeFreeCredentials cred = !UseNewCryptoApi || policy == EncryptionPolicy.NoEncryption ?
AcquireCredentialsHandleSchannelCred(certificateContext, protocols, policy, isServer) :
AcquireCredentialsHandleSchCredentials(certificateContext, protocols, policy, isServer);
if (certificateContext != null && certificateContext.Trust != null && certificateContext.Trust._sendTrustInHandshake)
try
{
AttachCertificateStore(cred, certificateContext.Trust._store!);
}
// New crypto API supports TLS1.3 but it does not allow to force NULL encryption.
SafeFreeCredentials cred = !UseNewCryptoApi || policy == EncryptionPolicy.NoEncryption ?
AcquireCredentialsHandleSchannelCred(certificateContext, protocols, policy, isServer) :
AcquireCredentialsHandleSchCredentials(certificateContext, protocols, policy, isServer);
if (certificateContext != null && certificateContext.Trust != null && certificateContext.Trust._sendTrustInHandshake)
{
AttachCertificateStore(cred, certificateContext.Trust._store!);
}

return cred;
return cred;
}
catch (Win32Exception e)
{
throw new AuthenticationException(SR.net_auth_SSPI, e);
}
}

private static unsafe void AttachCertificateStore(SafeFreeCredentials cred, X509Store store)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ public async Task ClientAsyncAuthenticate_EachSupportedProtocol_Success(SslProto
[Theory]
[MemberData(nameof(ProtocolMismatchData))]
public async Task ClientAsyncAuthenticate_MismatchProtocols_Fails(
SslProtocols serverProtocol,
SslProtocols clientProtocol,
SslProtocols serverProtocol,
Type expectedException)
{
Exception e = await Record.ExceptionAsync(() => ClientAsyncSslHelper(serverProtocol, clientProtocol));
Exception e = await Record.ExceptionAsync(() => ClientAsyncSslHelper(clientProtocol, serverProtocol));
Assert.NotNull(e);
Assert.IsAssignableFrom(expectedException, e);
}
Expand Down Expand Up @@ -92,17 +92,19 @@ public async Task ClientAsyncAuthenticate_IndividualServerVsAllClientSupportedPr

public static IEnumerable<object[]> ProtocolMismatchData()
{
#pragma warning disable 0618
yield return new object[] { SslProtocols.Ssl2, SslProtocols.Ssl3, typeof(Exception) };
yield return new object[] { SslProtocols.Ssl2, SslProtocols.Tls12, typeof(Exception) };
yield return new object[] { SslProtocols.Ssl3, SslProtocols.Tls12, typeof(Exception) };
#pragma warning restore 0618
yield return new object[] { SslProtocols.Tls, SslProtocols.Tls11, typeof(AuthenticationException) };
yield return new object[] { SslProtocols.Tls, SslProtocols.Tls12, typeof(AuthenticationException) };
yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls, typeof(AuthenticationException) };
yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls, typeof(AuthenticationException) };
yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls11, typeof(AuthenticationException) };
yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls12, typeof(AuthenticationException) };
var supportedProtocols = new SslProtocolSupport.SupportedSslProtocolsTestData();

foreach (var serverProtocols in supportedProtocols)
foreach (var clientProtocols in supportedProtocols)
{
SslProtocols serverProtocol = (SslProtocols)serverProtocols[0];
SslProtocols clientProtocol = (SslProtocols)clientProtocols[0];

if (clientProtocol != serverProtocol)
{
yield return new object[] { clientProtocol, serverProtocol, typeof(AuthenticationException) };
}
}
}

#region Helpers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public void EventSource_ExistsWithCorrectId()
[SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "X509 certificate store is not supported on iOS or tvOS.")] // Match SslStream_StreamToStream_Authentication_Success
public void EventSource_EventsRaisedAsExpected()
{
RemoteExecutor.Invoke(async () =>
RemoteExecutor.Invoke(async () =>
{
try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ public async Task ServerAsyncAuthenticate_EachSupportedProtocol_Success(SslProto
[Theory]
[MemberData(nameof(ProtocolMismatchData))]
public async Task ServerAsyncAuthenticate_MismatchProtocols_Fails(
SslProtocols serverProtocol,
SslProtocols clientProtocol,
SslProtocols serverProtocol,
Type expectedException)
{
Exception e = await Record.ExceptionAsync(
Expand Down Expand Up @@ -236,7 +236,7 @@ public async Task ServerAsyncAuthenticate_ConstructorVerificationDelegate_Succes

(Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams();
var client = new SslStream(clientStream);
var server = new SslStream(serverStream, false, (sender, certificate, chain, sslPolicyErrors) => { validationCallbackCalled = true; return true;});
var server = new SslStream(serverStream, false, (sender, certificate, chain, sslPolicyErrors) => { validationCallbackCalled = true; return true; });

using (client)
using (server)
Expand Down Expand Up @@ -323,37 +323,18 @@ public async Task ServerAsyncAuthenticate_InvalidHello_Throws(bool close)

public static IEnumerable<object[]> ProtocolMismatchData()
{
if (PlatformDetection.SupportsSsl3)
{
#pragma warning disable 0618
yield return new object[] { SslProtocols.Ssl3, SslProtocols.Tls12, typeof(Exception) };
if (PlatformDetection.SupportsSsl2)
{
yield return new object[] { SslProtocols.Ssl2, SslProtocols.Ssl3, typeof(Exception) };
yield return new object[] { SslProtocols.Ssl2, SslProtocols.Tls12, typeof(Exception) };
}
#pragma warning restore 0618
}

// It is OK if server does not support given protocol. It should still fail.
// But if client does not support it, it will simply fail without sending out any data.

if (PlatformDetection.SupportsTls10)
{
yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls, typeof(AuthenticationException) };
yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls, typeof(AuthenticationException) };
}
var supportedProtocols = new SslProtocolSupport.SupportedSslProtocolsTestData();

if (PlatformDetection.SupportsTls11)
foreach (var serverProtocols in supportedProtocols)
foreach (var clientProtocols in supportedProtocols)
{
yield return new object[] { SslProtocols.Tls, SslProtocols.Tls11, typeof(AuthenticationException) };
yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls11, typeof(AuthenticationException) };
}
SslProtocols serverProtocol = (SslProtocols)serverProtocols[0];
SslProtocols clientProtocol = (SslProtocols)clientProtocols[0];

if (PlatformDetection.SupportsTls12)
{
yield return new object[] { SslProtocols.Tls, SslProtocols.Tls12, typeof(AuthenticationException) };
yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls12, typeof(AuthenticationException) };
if (clientProtocol != serverProtocol)
{
yield return new object[] { clientProtocol, serverProtocol, typeof(AuthenticationException) };
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ public async Task ServerNoEncryption_ClientNoEncryption_ConnectWithNoEncryption(
else
{
var ae = await Assert.ThrowsAsync<AuthenticationException>(() => sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false));
Assert.IsType<PlatformNotSupportedException>(ae.InnerException);
if (!OperatingSystem.IsWindows())
{
Assert.IsType<PlatformNotSupportedException>(ae.InnerException);
Copy link
Member

Choose a reason for hiding this comment

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

Does this correlates anyhow with the new check for IsWindows10Version20348OrGreater in s_supportsNullEncryption?
If so, should it be the same check here as well? Or is this unrelated?

Copy link
Member Author

Choose a reason for hiding this comment

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

not necessarily. I'm not sure where the expected PlatformNotSupportedException would come from. On windows when the protocol are disabled in registry we get API failure. I mostly disabled this to pass the test so we have time to investigate. My intention is to stabilize the tests but leave #65098 open so we can investigate more.

}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,21 @@ public static Task WhenAllOrAnyFailedWithTimeout(params Task[] tasks)
// On Windows, null ciphers (no encryption) are supported.
if (OperatingSystem.IsWindows())
{
return true;
if (!PlatformDetection.IsWindows10OrLater)
{
// All old versions support null encryption
return true;
}

try
{
// New Windows can support null but it may be disabled in Azure images
using (Process p = Process.Start(new ProcessStartInfo("powershell", "-Command Get-TlsCipherSuite") { RedirectStandardOutput = true, RedirectStandardError = true }))
{
return p.StandardOutput.ReadToEnd().Contains("WITH_NULL");
}
}
catch { return true; } // assume availability
}

// On macOS and Android, the null cipher (no encryption) is not supported.
Expand Down