<data name="net_auth_eof" xml:space="preserve">
<value>Authentication failed because the remote party has closed the transport stream.</value>
</data>
+ <data name="net_auth_tls_alert" xml:space="preserve">
+ <value>Authentication failed because the remote party sent a TLS alert: '{0}'.</value>
+ </data>
<data name="net_auth_alert" xml:space="preserve">
<value>Authentication failed on the remote side (the stream might still be available for additional authentication attempts).</value>
</data>
<Compile Include="System\Net\Security\StreamSizes.cs" />
<Compile Include="System\Net\Security\TlsAlertType.cs" />
<Compile Include="System\Net\Security\TlsAlertMessage.cs" />
+ <Compile Include="System\Net\Security\TlsFrameHelper.cs" />
<Compile Include="System\Security\Authentication\AuthenticationException.cs" />
<!-- NegotiateStream -->
<Compile Include="System\Net\BufferAsyncResult.cs" />
//
// Acquire Server Side Certificate information and set it on the class.
//
- private bool AcquireServerCredentials(ref byte[]? thumbPrint, ReadOnlySpan<byte> clientHello)
+ private bool AcquireServerCredentials(ref byte[]? thumbPrint)
{
if (NetEventSource.IsEnabled)
NetEventSource.Enter(this);
// 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)
{
if (_refreshCredentialNeeded)
{
cachedCreds = _sslAuthenticationOptions.IsServer
- ? AcquireServerCredentials(ref thumbPrint, inputBuffer)
+ ? AcquireServerCredentials(ref thumbPrint)
: AcquireClientCredentials(ref thumbPrint);
}
// 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;
}
// } 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;
}
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
// 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<bool>? _handshakeWaiter;
{
// get ready to receive first frame
_handshakeBuffer = new ArrayBuffer(InitialHandshakeBufferSize);
- _framing = Framing.Unknown;
}
while (!handshakeCompleted)
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)
_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);
}
_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<byte> 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));
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);
Buffer.BlockCopy(saved, 0, buffer, 0, copyCount);
}
}
+
return buffer;
}
}
// 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)
{
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);
}
--- /dev/null
+// 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<byte> 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<byte> frame)
+ {
+ if (frame.Length < 5 || frame[1] < 3)
+ {
+ return - 1;
+ }
+
+ return ((frame[3] << 8) | frame[4]) + HeaderSize;
+ }
+
+ public static bool TryGetHandshakeInfo(ReadOnlySpan<byte> 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<byte> 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<byte>(),
+ };
+
+ 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<byte>();
+ }
+ }
+}
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<AuthenticationException>(
() => ClientAsyncSslHelper(
EncryptionPolicy.NoEncryption,
SslProtocolSupport.DefaultSslProtocols, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 ));
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
using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null))
{
- await Assert.ThrowsAsync(TestConfiguration.SupportsHandshakeAlerts ? typeof(AuthenticationException) : typeof(IOException), () =>
+ await Assert.ThrowsAsync<AuthenticationException>(() =>
sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false));
}
}
[Theory]
[MemberData(nameof(ProtocolMismatchData))]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/29642")]
public async Task ServerAsyncAuthenticate_MismatchProtocols_Fails(
SslProtocols serverProtocol,
SslProtocols clientProtocol,
#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
using (var sslStream = new SslStream(client.GetStream(), false, AllowAnyServerCertificate, null, EncryptionPolicy.RequireEncryption))
{
- await Assert.ThrowsAsync(TestConfiguration.SupportsHandshakeAlerts ? typeof(AuthenticationException) : typeof(IOException), () =>
+ await Assert.ThrowsAsync<AuthenticationException>(() =>
sslStream.AuthenticateAsClientAsync("localhost", null, SslProtocolSupport.DefaultSslProtocols, false));
}
}
// 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;
private async Task WithVirtualConnection(Func<SslStream, SslStream, Task> 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))
{
// 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;
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);
}
Link="ProductionCode\Common\System\Threading\Tasks\TaskToApm.cs" />
<Compile Include="..\..\src\System\Net\Security\SniHelper.cs"
Link="src\SniHelper.cs" />
+ <Compile Include="..\..\src\System\Net\Security\TlsFrameHelper.cs"
+ Link="src\TlsFrameHelper.cs" />
<Compile Include="SniHelperTest.cs" />
<Compile Include="SslAuthenticationOptionsTest.cs" />
<Compile Include="SslStreamAlertsTest.cs" />
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);