diff --git a/src/libraries/System.Net.Security/src/Resources/Strings.resx b/src/libraries/System.Net.Security/src/Resources/Strings.resx index 7270ea80faefd..8af05ebe134c8 100644 --- a/src/libraries/System.Net.Security/src/Resources/Strings.resx +++ b/src/libraries/System.Net.Security/src/Resources/Strings.resx @@ -212,6 +212,9 @@ Authentication failed because the remote party has closed the transport stream. + + Authentication failed because the remote party sent a TLS alert: '{0}'. + Authentication failed on the remote side (the stream might still be available for additional authentication attempts). diff --git a/src/libraries/System.Net.Security/src/System.Net.Security.csproj b/src/libraries/System.Net.Security/src/System.Net.Security.csproj index 868faddb5727a..067df9b00fcf6 100644 --- a/src/libraries/System.Net.Security/src/System.Net.Security.csproj +++ b/src/libraries/System.Net.Security/src/System.Net.Security.csproj @@ -34,6 +34,7 @@ + diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs index 82aab9fe95196..b770ef26fb78a 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs @@ -625,7 +625,7 @@ private bool AcquireClientCredentials(ref byte[]? thumbPrint) // // Acquire Server Side Certificate information and set it on the class. // - private bool AcquireServerCredentials(ref byte[]? thumbPrint, ReadOnlySpan clientHello) + private bool AcquireServerCredentials(ref byte[]? thumbPrint) { if (NetEventSource.IsEnabled) NetEventSource.Enter(this); @@ -639,13 +639,13 @@ private bool AcquireServerCredentials(ref byte[]? thumbPrint, ReadOnlySpan // with .NET Framework), and if neither is set we fall back to using ServerCertificate. if (_sslAuthenticationOptions.ServerCertSelectionDelegate != null) { - string? serverIdentity = SniHelper.GetServerName(clientHello); - localCertificate = _sslAuthenticationOptions.ServerCertSelectionDelegate(serverIdentity); - + localCertificate = _sslAuthenticationOptions.ServerCertSelectionDelegate(_sslAuthenticationOptions.TargetHost); if (localCertificate == null) { throw new AuthenticationException(SR.net_ssl_io_no_server_cert); } + if (NetEventSource.IsEnabled) + NetEventSource.Info(this, "Use delegate selected Cert"); } else if (_sslAuthenticationOptions.CertSelectionDelegate != null) { @@ -784,7 +784,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan inputBuffer, ref byte if (_refreshCredentialNeeded) { cachedCreds = _sslAuthenticationOptions.IsServer - ? AcquireServerCredentials(ref thumbPrint, inputBuffer) + ? AcquireServerCredentials(ref thumbPrint) : AcquireClientCredentials(ref thumbPrint); } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SniHelper.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SniHelper.cs index ffbf730e7d971..db682188997e1 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SniHelper.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SniHelper.cs @@ -26,13 +26,13 @@ internal class SniHelper // opaque fragment[SSLPlaintext.length]; // } SSLPlaintext; const int ContentTypeOffset = 0; - const int ProtocolVersionOffset = ContentTypeOffset + sizeof(ContentType); + const int ProtocolVersionOffset = ContentTypeOffset + sizeof(TlsContentType); const int LengthOffset = ProtocolVersionOffset + ProtocolVersionSize; const int HandshakeOffset = LengthOffset + sizeof(ushort); // SSL v2's ContentType has 0x80 bit set. // We do not care about SSL v2 here because it does not support client hello extensions - if (sslPlainText.Length < HandshakeOffset || (ContentType)sslPlainText[ContentTypeOffset] != ContentType.Handshake) + if (sslPlainText.Length < HandshakeOffset || (TlsContentType)sslPlainText[ContentTypeOffset] != TlsContentType.Handshake) { return null; } @@ -62,10 +62,10 @@ internal class SniHelper // } body; // } Handshake; const int HandshakeTypeOffset = 0; - const int ClientHelloLengthOffset = HandshakeTypeOffset + sizeof(HandshakeType); + const int ClientHelloLengthOffset = HandshakeTypeOffset + sizeof(TlsHandshakeType); const int ClientHelloOffset = ClientHelloLengthOffset + UInt24Size; - if (sslHandshake.Length < ClientHelloOffset || (HandshakeType)sslHandshake[HandshakeTypeOffset] != HandshakeType.ClientHello) + if (sslHandshake.Length < ClientHelloOffset || (TlsHandshakeType)sslHandshake[HandshakeTypeOffset] != TlsHandshakeType.ClientHello) { return null; } @@ -363,16 +363,6 @@ private static Encoding CreateEncoding() return Encoding.GetEncoding("utf-8", new EncoderExceptionFallback(), new DecoderExceptionFallback()); } - private enum ContentType : byte - { - Handshake = 0x16 - } - - private enum HandshakeType : byte - { - ClientHello = 0x01 - } - private enum ExtensionType : ushort { ServerName = 0x00 diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs index 600163be36290..d9ff52dfeba8f 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Implementation.cs @@ -34,14 +34,8 @@ private enum Framing // This is set on the first packet to figure out the framing style. private Framing _framing = Framing.Unknown; - // SSL3/TLS protocol frames definitions. - private enum FrameType : byte - { - ChangeCipherSpec = 20, - Alert = 21, - Handshake = 22, - AppData = 23 - } + private TlsAlertDescription _lastAlertDescription; + private TlsFrameHandshakeInfo _lastFrame; private readonly object _handshakeLock = new object(); private volatile TaskCompletionSource? _handshakeWaiter; @@ -274,7 +268,6 @@ private async Task ForceAuthenticationAsync(TIOAdapter adapter, bool { // get ready to receive first frame _handshakeBuffer = new ArrayBuffer(InitialHandshakeBufferSize); - _framing = Framing.Unknown; } while (!handshakeCompleted) @@ -288,6 +281,19 @@ private async Task ForceAuthenticationAsync(TIOAdapter adapter, bool if (message.Failed) { + if (_lastFrame.Header.Type == TlsContentType.Handshake && message.Size == 0) + { + // If we failed without OS sending out alert, inject one here to be consistent across platforms. + byte[] alert = TlsFrameHelper.CreateAlertFrame(_lastFrame.Header.Version, TlsAlertDescription.ProtocolVersion); + await adapter.WriteAsync(alert, 0, alert.Length).ConfigureAwait(false); + } + else if (_lastFrame.Header.Type == TlsContentType.Alert && _lastAlertDescription != TlsAlertDescription.CloseNotify && + message.Status.ErrorCode == SecurityStatusPalErrorCode.IllegalMessage) + { + // Improve generic message and show details if we failed because of TLS Alert. + throw new AuthenticationException(SR.Format(SR.net_auth_tls_alert, _lastAlertDescription.ToString()), message.GetException()); + } + throw new AuthenticationException(SR.net_auth_SSPI, message.GetException()); } else if (message.Status.ErrorCode == SecurityStatusPalErrorCode.OK) @@ -346,17 +352,49 @@ private async ValueTask ReceiveBlobAsync(TIOAdapter a _framing = DetectFraming(_handshakeBuffer.ActiveReadOnlySpan); } - int frameSize = GetFrameSize(_handshakeBuffer.ActiveReadOnlySpan); - if (frameSize < 0) + if (_framing == Framing.BeforeSSL3) + { +#pragma warning disable 0618 + _lastFrame.Header.Version = SslProtocols.Ssl2; +#pragma warning restore 0618 + _lastFrame.Header.Length = GetFrameSize(_handshakeBuffer.ActiveReadOnlySpan); + } + else + { + TlsFrameHelper.TryGetFrameHeader(_handshakeBuffer.ActiveReadOnlySpan, ref _lastFrame.Header); + } + + if (_lastFrame.Header.Length < 0) { throw new IOException(SR.net_frame_read_size); } + // Header length is content only so we must add header size as well. + int frameSize = _lastFrame.Header.Length + TlsFrameHelper.HeaderSize; if (_handshakeBuffer.ActiveLength < frameSize) { await FillHandshakeBufferAsync(adapter, frameSize).ConfigureAwait(false); } + // At this point, we have at least one TLS frame. + if (_lastFrame.Header.Type == TlsContentType.Alert) + { + TlsAlertLevel level = 0; + if (TlsFrameHelper.TryGetAlertInfo(_handshakeBuffer.ActiveReadOnlySpan, ref level, ref _lastAlertDescription)) + { + if (NetEventSource.IsEnabled && _lastAlertDescription != TlsAlertDescription.CloseNotify) NetEventSource.Fail(this, $"Received TLS alert {_lastAlertDescription}"); + } + } + else if (_lastFrame.Header.Type == TlsContentType.Handshake) + { + if (_handshakeBuffer.ActiveReadOnlySpan[TlsFrameHelper.HeaderSize] == (byte)TlsHandshakeType.ClientHello && + _sslAuthenticationOptions!.ServerCertSelectionDelegate != null) + { + // Process SNI from Client Hello message + TlsFrameHelper.TryGetHandshakeInfo(_handshakeBuffer.ActiveReadOnlySpan, ref _lastFrame); + _sslAuthenticationOptions.TargetHost = _lastFrame.TargetName; + } + } return ProcessBlob(frameSize); } @@ -372,23 +410,24 @@ private ProtocolToken ProcessBlob(int frameSize) _handshakeBuffer.Discard(frameSize); // Often more TLS messages fit into same packet. Get as many complete frames as we can. - while (_handshakeBuffer.ActiveLength > SecureChannel.ReadHeaderSize) + while (_handshakeBuffer.ActiveLength > TlsFrameHelper.HeaderSize) { - ReadOnlySpan remainingData = _handshakeBuffer.ActiveReadOnlySpan; - if (remainingData[0] >= (int)FrameType.AppData) + TlsFrameHeader nextHeader = default; + + if (!TlsFrameHelper.TryGetFrameHeader(_handshakeBuffer.ActiveReadOnlySpan, ref nextHeader)) { break; } - frameSize = GetFrameSize(remainingData); - if (_handshakeBuffer.ActiveLength >= frameSize) + frameSize = nextHeader.Length + TlsFrameHelper.HeaderSize; + if (nextHeader.Type == TlsContentType.AppData || frameSize > _handshakeBuffer.ActiveLength) { - chunkSize += frameSize; - _handshakeBuffer.Discard(frameSize); - continue; + // We don't have full frame left or we already have app data which needs to be processed by decrypt. + break; } - break; + chunkSize += frameSize; + _handshakeBuffer.Discard(frameSize); } return _context!.NextMessage(availableData.Slice(0, chunkSize)); @@ -645,7 +684,7 @@ private async ValueTask ReadAsyncInternal(TIOAdapter adapter, M Debug.Assert(_internalBufferCount >= SecureChannel.ReadHeaderSize); // Parse the frame header to determine the payload size (which includes the header size). - int payloadBytes = GetFrameSize(_internalBuffer.AsSpan(_internalOffset)); + int payloadBytes = TlsFrameHelper.GetFrameSize(_internalBuffer.AsSpan(_internalOffset)); if (payloadBytes < 0) { throw new IOException(SR.net_frame_read_size); @@ -913,6 +952,7 @@ private static byte[] EnsureBufferSize(byte[] buffer, int copyCount, int size) Buffer.BlockCopy(saved, 0, buffer, 0, copyCount); } } + return buffer; } @@ -1003,8 +1043,8 @@ private Framing DetectFraming(ReadOnlySpan bytes) } // If the first byte is SSL3 HandShake, then check if we have a SSLv3 Type3 client hello. - if (bytes[0] == (byte)FrameType.Handshake || bytes[0] == (byte)FrameType.AppData - || bytes[0] == (byte)FrameType.Alert) + if (bytes[0] == (byte)TlsContentType.Handshake || bytes[0] == (byte)TlsContentType.AppData + || bytes[0] == (byte)TlsContentType.Alert) { if (bytes.Length < 3) { diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs index b72e549355fdc..3cf26e783a9d0 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.OSX.cs @@ -237,9 +237,8 @@ private static SecurityStatusPal HandshakeInternal( sslContext = new SafeDeleteSslContext((credential as SafeFreeSslCredentials)!, sslAuthenticationOptions); context = sslContext; - if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost)) + if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) && !sslAuthenticationOptions.IsServer) { - Debug.Assert(!sslAuthenticationOptions.IsServer, "targetName should not be set for server-side handshakes"); Interop.AppleCrypto.SslSetTargetName(sslContext.SslContext, sslAuthenticationOptions.TargetHost); } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/TlsFrameHelper.cs b/src/libraries/System.Net.Security/src/System/Net/Security/TlsFrameHelper.cs new file mode 100644 index 0000000000000..ec18be1b8e374 --- /dev/null +++ b/src/libraries/System.Net.Security/src/System/Net/Security/TlsFrameHelper.cs @@ -0,0 +1,235 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Security.Authentication; + +namespace System.Net.Security +{ + // SSL3/TLS protocol frames definitions. + internal enum TlsContentType : byte + { + ChangeCipherSpec = 20, + Alert = 21, + Handshake = 22, + AppData = 23 + } + + internal enum TlsHandshakeType : byte + { + HelloRequest = 0, + ClientHello = 1, + ServerHello = 2, + NewSessionTicket = 4, + EndOfEarlyData = 5, + EncryptedExtensions = 8, + Certificate = 11, + ServerKeyExchange = 12, + CertificateRequest = 13, + ServerHelloDone = 14, + CertificateVerify = 15, + ClientKeyExchange = 16, + Finished = 20, + KeyEpdate = 24, + MessageHash = 254 + } + + internal enum TlsAlertLevel : byte + { + Warning = 1, + Fatal = 2, + } + + internal enum TlsAlertDescription : byte + { + CloseNotify = 0, // warning + UnexpectedMessage = 10, // error + BadRecordMac = 20, // error + DecryptionFailed = 21, // reserved + RecordOverflow = 22, // error + DecompressionFail = 30, // error + HandshakeFailure = 40, // error + BadCertificate = 42, // warning or error + UnsupportedCert = 43, // warning or error + CertificateRevoked = 44, // warning or error + CertificateExpired = 45, // warning or error + CertificateUnknown = 46, // warning or error + IllegalParameter = 47, // error + UnknownCA = 48, // error + AccessDenied = 49, // error + DecodeError = 50, // error + DecryptError = 51, // error + ExportRestriction = 60, // reserved + ProtocolVersion = 70, // error + InsuffientSecurity = 71, // error + InternalError = 80, // error + UserCanceled = 90, // warning or error + NoRenegotiation = 100, // warning + UnsupportedExt = 110, // error + } + + internal struct TlsFrameHeader + { + public TlsContentType Type; + public SslProtocols Version; + public int Length; + } + + internal struct TlsFrameHandshakeInfo + { + public TlsFrameHeader Header; + public TlsHandshakeType HandshakeType; + public SslProtocols SupportedVersions; + public string? TargetName; + } + + internal class TlsFrameHelper + { + public const int HeaderSize = 5; + + private static byte[] s_protocolMismatch13 = new byte[] { (byte)TlsContentType.Alert, 3, 4, 0, 2, 2, 70 }; + private static byte[] s_protocolMismatch12 = new byte[] { (byte)TlsContentType.Alert, 3, 3, 0, 2, 2, 70 }; + private static byte[] s_protocolMismatch11 = new byte[] { (byte)TlsContentType.Alert, 3, 2, 0, 2, 2, 70 }; + private static byte[] s_protocolMismatch10 = new byte[] { (byte)TlsContentType.Alert, 3, 1, 0, 2, 2, 70 }; + + public static bool TryGetFrameHeader(ReadOnlySpan frame, ref TlsFrameHeader header) + { + bool result = frame.Length > 4; + + if (frame.Length >= 1) + { + header.Type = (TlsContentType)frame[0]; + + if (frame.Length >= 3) + { + // SSLv3, TLS or later + if (frame[1] == 3) + { + if (frame.Length > 4) + { + header.Length = ((frame[3] << 8) | frame[4]); + } + + switch (frame[2]) + { + case 4: + header.Version = SslProtocols.Tls13; + break; + case 3: + header.Version = SslProtocols.Tls12; + break; + case 2: + header.Version = SslProtocols.Tls11; + break; + case 1: + header.Version = SslProtocols.Tls; + break; + case 0: +#pragma warning disable 0618 + header.Version = SslProtocols.Ssl3; +#pragma warning restore 0618 + break; + default: + header.Version = SslProtocols.None; + break; + } + } + else + { + header.Length = -1; + header.Version = SslProtocols.None; + } + } + } + + return result; + } + + // Returns frame size e.g. header + content + public static int GetFrameSize(ReadOnlySpan frame) + { + if (frame.Length < 5 || frame[1] < 3) + { + return - 1; + } + + return ((frame[3] << 8) | frame[4]) + HeaderSize; + } + + public static bool TryGetHandshakeInfo(ReadOnlySpan frame, ref TlsFrameHandshakeInfo info) + { + if (frame.Length < 6 || frame[0] != (byte)TlsContentType.Handshake) + { + return false; + } + + // This will not fail since we have enough data. + bool gotHeader = TryGetFrameHeader(frame, ref info.Header); + Debug.Assert(gotHeader); + + info.SupportedVersions = info.Header.Version; + + info.HandshakeType = (TlsHandshakeType)frame[5]; + + if (info.HandshakeType == TlsHandshakeType.ClientHello) + { + info.TargetName = SniHelper.GetServerName(frame); + } + + return true; + } + + public static bool TryGetAlertInfo(ReadOnlySpan frame, ref TlsAlertLevel level, ref TlsAlertDescription description) + { + if (frame.Length < 7 || frame[0] != (byte)TlsContentType.Alert) + { + return false; + } + + level = (TlsAlertLevel)frame[5]; + description = (TlsAlertDescription)frame[6]; + + return true; + } + + private static byte[] CreateProtocolVersionAlert(SslProtocols version) => + version switch + { + SslProtocols.Tls13 => s_protocolMismatch13, + SslProtocols.Tls12 => s_protocolMismatch12, + SslProtocols.Tls11 => s_protocolMismatch11, + SslProtocols.Tls => s_protocolMismatch10, + _ => Array.Empty(), + }; + + public static byte[] CreateAlertFrame(SslProtocols version, TlsAlertDescription reason) + { + if (reason == TlsAlertDescription.ProtocolVersion) + { + return CreateProtocolVersionAlert(version); + } + else if ((int)version > (int)SslProtocols.Tls) + { + // Create TLS1.2 alert + byte[] buffer = new byte[] { (byte)TlsContentType.Alert, 3, 3, 0, 2, 2, (byte)reason }; + switch (version) + { + case SslProtocols.Tls13: + buffer[2] = 4; + break; + case SslProtocols.Tls11: + buffer[2] = 2; + break; + case SslProtocols.Tls: + buffer[2] = 1; + break; + } + + return buffer; + } + + return Array.Empty(); + } + } +} diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs index 69c96735809da..5c227192f2448 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientAsyncAuthenticateTest.cs @@ -44,11 +44,7 @@ public async Task ClientAsyncAuthenticate_ServerRequireEncryption_ConnectWithEnc public async Task ClientAsyncAuthenticate_ServerNoEncryption_NoConnect() { // Don't use Tls13 since we are trying to use NullEncryption - Type expectedExceptionType = TestConfiguration.SupportsHandshakeAlerts && TestConfiguration.SupportsNullEncryption ? - typeof(AuthenticationException) : - typeof(IOException); - - await Assert.ThrowsAsync(expectedExceptionType, + await Assert.ThrowsAsync( () => ClientAsyncSslHelper( EncryptionPolicy.NoEncryption, SslProtocolSupport.DefaultSslProtocols, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 )); @@ -120,12 +116,12 @@ public static IEnumerable ProtocolMismatchData() 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, TestConfiguration.SupportsVersionAlerts ? typeof(AuthenticationException) : typeof(IOException) }; - yield return new object[] { SslProtocols.Tls, SslProtocols.Tls12, TestConfiguration.SupportsVersionAlerts ? typeof(AuthenticationException) : typeof(IOException) }; + 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, TestConfiguration.SupportsVersionAlerts ? typeof(AuthenticationException) : typeof(IOException) }; + yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls12, typeof(AuthenticationException) }; } #region Helpers diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientDefaultEncryptionTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientDefaultEncryptionTest.cs index 4a57ca9063161..ed3a2c635e692 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ClientDefaultEncryptionTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ClientDefaultEncryptionTest.cs @@ -84,7 +84,7 @@ public async Task ClientDefaultEncryption_ServerNoEncryption_NoConnect() using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null)) { - await Assert.ThrowsAsync(TestConfiguration.SupportsHandshakeAlerts ? typeof(AuthenticationException) : typeof(IOException), () => + await Assert.ThrowsAsync(() => sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false)); } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs index 5ecb21d630a9a..9bf0afb5b2290 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerAsyncAuthenticateTest.cs @@ -44,7 +44,6 @@ public async Task ServerAsyncAuthenticate_EachSupportedProtocol_Success(SslProto [Theory] [MemberData(nameof(ProtocolMismatchData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/29642")] public async Task ServerAsyncAuthenticate_MismatchProtocols_Fails( SslProtocols serverProtocol, SslProtocols clientProtocol, @@ -80,10 +79,10 @@ public static IEnumerable ProtocolMismatchData() #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, TestConfiguration.SupportsVersionAlerts ? typeof(AuthenticationException) : typeof(TimeoutException) }; + yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls, typeof(AuthenticationException) }; yield return new object[] { SslProtocols.Tls11, SslProtocols.Tls12, typeof(AuthenticationException) }; - yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls, TestConfiguration.SupportsVersionAlerts ? typeof(AuthenticationException) : typeof(TimeoutException) }; - yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls11, TestConfiguration.SupportsVersionAlerts ? typeof(AuthenticationException) : typeof(TimeoutException) }; + yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls, typeof(AuthenticationException) }; + yield return new object[] { SslProtocols.Tls12, SslProtocols.Tls11, typeof(AuthenticationException) }; } #region Helpers diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerNoEncryptionTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerNoEncryptionTest.cs index 65efb78767f9c..d062fac791c1d 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/ServerNoEncryptionTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/ServerNoEncryptionTest.cs @@ -43,7 +43,7 @@ public async Task ServerNoEncryption_ClientRequireEncryption_NoConnect() using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null, EncryptionPolicy.RequireEncryption)) { - await Assert.ThrowsAsync(TestConfiguration.SupportsHandshakeAlerts ? typeof(AuthenticationException) : typeof(IOException), () => + await Assert.ThrowsAsync(() => sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false)); } } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSniTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSniTest.cs index a54624100da2a..b98a9ea992bde 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSniTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSniTest.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.IO; using System.Net.Test.Common; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; @@ -201,9 +202,7 @@ private static SslServerAuthenticationOptions DefaultServerOptions() private async Task WithVirtualConnection(Func serverClientConnection, RemoteCertificateValidationCallback clientCertValidate) { - VirtualNetwork vn = new VirtualNetwork(); - using (VirtualNetworkStream serverStream = new VirtualNetworkStream(vn, isServer: true), - clientStream = new VirtualNetworkStream(vn, isServer: false)) + (Stream clientStream, Stream serverStream) = TestHelper.GetConnectedStreams(); using (SslStream server = new SslStream(serverStream, leaveInnerStreamOpen: false), client = new SslStream(clientStream, leaveInnerStreamOpen: false, clientCertValidate)) { diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSystemDefaultsTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSystemDefaultsTest.cs index 4943401bc51ee..bc704fae67fda 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSystemDefaultsTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSystemDefaultsTest.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.IO; using System.Net.Http; using System.Net.Test.Common; using System.Security.Cryptography.X509Certificates; @@ -21,10 +22,7 @@ public abstract class SslStreamSystemDefaultTest public SslStreamSystemDefaultTest() { - var network = new VirtualNetwork(); - var clientNet = new VirtualNetworkStream(network, isServer:false); - var serverNet = new VirtualNetworkStream(network, isServer: true); - + (Stream clientNet, Stream serverNet) = TestHelper.GetConnectedTcpStreams(); _clientStream = new SslStream(clientNet, false, ClientCertCallback); _serverStream = new SslStream(serverNet, false, ServerCertCallback); } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj index ef6656e25ae68..5d6c539aedfe3 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj @@ -68,6 +68,8 @@ + diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/TestConfiguration.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/TestConfiguration.cs index 9769590181342..577d2ce1f58ef 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/TestConfiguration.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/TestConfiguration.cs @@ -32,9 +32,7 @@ internal static class TestConfiguration public static bool SupportsHandshakeAlerts { get { return RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.Windows); } } - public static bool SupportsAlpnAlerts { get { return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && PlatformDetection.OpenSslVersion.CompareTo(new Version(1,1,0)) >= 0); } } - - public static bool SupportsVersionAlerts { get { return RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && PlatformDetection.OpenSslVersion.CompareTo(new Version(1,1,0)) >= 0; } } + public static bool SupportsAlpnAlerts { get { return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && PlatformDetection.OpenSslVersion.CompareTo(new Version(1,0,2)) >= 0); } } public static Task WhenAllOrAnyFailedWithTimeout(params Task[] tasks) => tasks.WhenAllOrAnyFailed(PassingTestTimeoutMilliseconds);