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 @@ -43,6 +43,8 @@ private enum Framing
private const int FrameOverhead = 64;
private const int ReadBufferSize = 4096 * 4 + FrameOverhead; // We read in 16K chunks + headers.
private const int InitialHandshakeBufferSize = 4096 + FrameOverhead; // try to fit at least 4K ServerCertificate
private const int HandshakeTypeOffsetSsl2 = 2; // Offset of HelloType in Sslv2 and Unified frames
private const int HandshakeTypeOffsetTls = 5; // Offset of HelloType in Sslv3 and TLS frames
private ArrayBuffer _handshakeBuffer;
private bool _receivedEOF;

Expand Down Expand Up @@ -475,6 +477,7 @@ private async ValueTask<ProtocolToken> ReceiveBlobAsync<TIOAdapter>(TIOAdapter a
#pragma warning disable 0618
_lastFrame.Header.Version = SslProtocols.Ssl2;
#pragma warning restore 0618
_lastFrame.Header.Type = TlsContentType.Handshake; // Implied. We only call this during handshake and SSL2 does not have framing layer.
_lastFrame.Header.Length = GetFrameSize(_handshakeBuffer.ActiveReadOnlySpan) - TlsFrameHelper.HeaderSize;
}
else
Expand Down Expand Up @@ -506,9 +509,11 @@ private async ValueTask<ProtocolToken> ReceiveBlobAsync<TIOAdapter>(TIOAdapter a
}
break;
case TlsContentType.Handshake:
if (!_isRenego && _handshakeBuffer.ActiveReadOnlySpan[TlsFrameHelper.HeaderSize] == (byte)TlsHandshakeType.ClientHello &&
(_sslAuthenticationOptions!.ServerCertSelectionDelegate != null ||
_sslAuthenticationOptions!.ServerOptionDelegate != null))
byte handshakeType = _handshakeBuffer.ActiveReadOnlySpan[_framing == Framing.SinceSSL3 ? HandshakeTypeOffsetTls : HandshakeTypeOffsetSsl2];

if (!_isRenego &&
(_sslAuthenticationOptions!.ServerCertSelectionDelegate != null || _sslAuthenticationOptions!.ServerOptionDelegate != null) &&
(handshakeType == (byte)TlsHandshakeType.ClientHello))
{
TlsFrameHelper.ProcessingOptions options = NetEventSource.Log.IsEnabled() ?
TlsFrameHelper.ProcessingOptions.All :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,33 +173,41 @@ public override string ToString()

public static bool TryGetFrameHeader(ReadOnlySpan<byte> frame, ref TlsFrameHeader header)
{
bool result = frame.Length > 4;

if (frame.Length >= 1)
header.Type = (TlsContentType)(frame.Length >= 1 ? frame[0] : 0);
if (frame.Length < TlsFrameHelper.HeaderSize)
{
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]);
}
header.Length = -1;
header.Version = SslProtocols.None;
return false;
}

header.Version = TlsMinorVersionToProtocol(frame[2]);
}
else
{
header.Length = -1;
header.Version = SslProtocols.None;
}
}
// SSLv3, TLS or later
if (frame[1] == ProtocolVersionTlsMajorValue)
{
header.Length = ((frame[3] << 8) | frame[4]);
header.Version = TlsMinorVersionToProtocol(frame[2]);
}
// Sslv2 or Unified
else if (frame[2] == (byte)TlsHandshakeType.ClientHello &&
frame[3] == ProtocolVersionTlsMajorValue) // SSL3 or above
{
header.Length = (frame[0] & 0x80) != 0 ?
(((frame[0] & 0x7f) << 8) | frame[1]) + 2 : // two bytes
(((frame[0] & 0x3f) << 8) | frame[1]) + 3; // three bytes
#pragma warning disable CS0618 // Ssl2 and Ssl3 are obsolete
header.Version = SslProtocols.Ssl2;
#pragma warning restore CS0618
header.Type = TlsContentType.Handshake;
}
else
{
// neither looks like TLS nor Ssl2 Hello
header.Length = -1;
header.Version = SslProtocols.None;
return false;
}

return result;
return true;
}

// Returns frame size e.g. header + content
Expand Down Expand Up @@ -252,6 +260,18 @@ public static bool TryGetFrameInfo(ReadOnlySpan<byte> frame, ref TlsFrameInfo in
}

info.HandshakeType = (TlsHandshakeType)frame[HandshakeTypeOffset];
#pragma warning disable CS0618 // Ssl2 and Ssl3 are obsolete
if (info.Header.Version == SslProtocols.Ssl2)
{
// This is safe. We would not get here if the length is too small.
info.SupportedVersions |= TlsMinorVersionToProtocol(frame[4]);
// We only recognize Unified ClientHello at the moment.
// This is needed to trigger certificate selection callback in SslStream.
info.HandshakeType = TlsHandshakeType.ClientHello;
// There is no more parsing for old protocols.
return true;
}
#pragma warning restore CS0618

// Check if we have full frame.
bool isComplete = frame.Length >= HeaderSize + info.Header.Length;
Expand Down Expand Up @@ -404,10 +424,10 @@ private static bool TryParseClientHello(ReadOnlySpan<byte> clientHello, ref TlsF
// Skip compression methods (max size 2^8-1 => size fits in 1 byte)
p = SkipOpaqueType1(p);

// is invalid structure or no extensions?
// no extensions
if (p.IsEmpty)
{
return false;
return true;
}

// client_hello_extension_list (max size 2^16-1 => size fits in 2 bytes)
Expand Down