Skip to content

Commit

Permalink
update SSL tests to deal better with disabled protocols (#65120)
Browse files Browse the repository at this point in the history
* update SSL tests to deal better with disabled protocols

* Improve detection of Null encryption on Windows

* update expectation for Mismatched protocols

* update detection

* wrap win32 exception

* update ProtocolMismatchData sets

* remove debug print

* final cleanup

* generate mismatch data

* avoid SslProtocols.Default
  • Loading branch information
wfurt authored Feb 17, 2022
1 parent 50b4abb commit 36a79fc
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 55 deletions.
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);
}
}
}
}
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

0 comments on commit 36a79fc

Please sign in to comment.