Commit 0d8dbf74 authored by Honfika's avatar Honfika

Forget to commit some files

parent 20df2e6e
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy
{
public class ClientHelloInfo
{
private static readonly string[] compressions = {
"null",
"DEFLATE"
};
public int MajorVersion { get; set; }
public int MinorVersion { get; set; }
public byte[] Random { get; set; }
public DateTime Time
{
get
{
DateTime time = DateTime.MinValue;
if (Random.Length > 3)
{
time = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)
.AddSeconds(((uint)Random[3] << 24) + ((uint)Random[2] << 16) + ((uint)Random[1] << 8) + (uint)Random[0]).ToLocalTime();
}
return time;
}
}
public byte[] SessionId { get; set; }
public int[] Ciphers { get; set; }
public byte[] CompressionData { get; set; }
internal int ClientHelloLength { get; set; }
internal int EntensionsStartPosition { get; set; }
public Dictionary<string, SslExtension> Extensions { get; set; }
private static string SslVersionToString(int major, int minor)
{
string str = "Unknown";
if (major == 3 && minor == 3)
str = "TLS/1.2";
else if (major == 3 && minor == 2)
str = "TLS/1.1";
else if (major == 3 && minor == 1)
str = "TLS/1.0";
else if (major == 3 && minor == 0)
str = "SSL/3.0";
else if (major == 2 && minor == 0)
str = "SSL/2.0";
return $"{major}.{minor} ({str})";
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine("A SSLv3-compatible ClientHello handshake was found. Titanium extracted the parameters below.");
sb.AppendLine();
sb.AppendLine($"Version: {SslVersionToString(MajorVersion, MinorVersion)}");
sb.AppendLine($"Random: {string.Join(" ", Random.Select(x => x.ToString("X2")))}");
sb.AppendLine($"\"Time\": {Time}");
sb.AppendLine($"SessionID: {string.Join(" ", SessionId.Select(x => x.ToString("X2")))}");
if (Extensions != null)
{
sb.AppendLine("Extensions:");
foreach (var extension in Extensions.Values.OrderBy(x => x.Position))
{
sb.AppendLine($"{extension.Name}: {extension.Data}");
}
}
if (CompressionData.Length > 0)
{
int compressionMethod = CompressionData[0];
string compression = compressions.Length > compressionMethod
? compressions[compressionMethod]
: $"unknown [0x{compressionMethod:X2}]";
sb.AppendLine($"Compression: {compression}");
}
if (Ciphers.Length > 0)
{
sb.AppendLine("Ciphers:");
foreach (int cipherSuite in Ciphers)
{
if (!SslCiphers.Ciphers.TryGetValue(cipherSuite, out string cipherStr))
{
cipherStr = "unknown";
}
sb.AppendLine($"[0x{cipherSuite:X4}] {cipherStr}");
}
}
return sb.ToString();
}
}
}
\ No newline at end of file
using StreamExtended.Network; using System;
using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Network;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
......
using StreamExtended.Network; using System;
using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
......
using System; using System;
using StreamExtended.Network;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Shared; using Titanium.Web.Proxy.Shared;
namespace Titanium.Web.Proxy.Http namespace Titanium.Web.Proxy.Http
......
This diff is collapsed.
namespace Titanium.Web.Proxy.Models
{
public class SslExtension
{
public int Value { get; }
public string Name { get; }
public string Data { get; }
public int Position { get; }
public SslExtension(int value, string name, string data, int position)
{
Value = value;
Name = name;
Data = data;
Position = position;
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using StreamExtended.Helpers;
namespace Titanium.Web.Proxy.Network
{
/// <summary>
/// A custom binary reader that would allo us to read string line by line
/// using the specified encoding
/// as well as to read bytes as required
/// </summary>
public class CustomBinaryReader : IDisposable
{
private readonly IBufferedStream stream;
private readonly Encoding encoding;
private bool disposed;
public byte[] Buffer { get; }
public CustomBinaryReader(IBufferedStream stream, int bufferSize)
{
this.stream = stream;
Buffer = BufferPool.GetBuffer(bufferSize);
//default to UTF-8
encoding = Encoding.UTF8;
}
/// <summary>
/// Read a line from the byte stream
/// </summary>
/// <returns></returns>
public async Task<string> ReadLineAsync()
{
byte lastChar = default(byte);
int bufferDataLength = 0;
// try to use the thread static buffer, usually it is enough
var buffer = Buffer;
while (stream.DataAvailable || await stream.FillBufferAsync())
{
byte newChar = stream.ReadByteFromBuffer();
buffer[bufferDataLength] = newChar;
//if new line
if (lastChar == '\r' && newChar == '\n')
{
return encoding.GetString(buffer, 0, bufferDataLength - 1);
}
//end of stream
if (newChar == '\0')
{
return encoding.GetString(buffer, 0, bufferDataLength);
}
bufferDataLength++;
//store last char for new line comparison
lastChar = newChar;
if (bufferDataLength == buffer.Length)
{
ResizeBuffer(ref buffer, bufferDataLength * 2);
}
}
if (bufferDataLength == 0)
{
return null;
}
return encoding.GetString(buffer, 0, bufferDataLength);
}
/// <summary>
/// Read until the last new line
/// </summary>
/// <returns></returns>
public async Task<List<string>> ReadAllLinesAsync()
{
string tmpLine;
var requestLines = new List<string>();
while (!string.IsNullOrEmpty(tmpLine = await ReadLineAsync()))
{
requestLines.Add(tmpLine);
}
return requestLines;
}
/// <summary>
/// Read until the last new line, ignores the result
/// </summary>
/// <returns></returns>
public async Task ReadAndIgnoreAllLinesAsync()
{
while (!string.IsNullOrEmpty(await ReadLineAsync()))
{
}
}
/// <summary>
/// Read the specified number (or less) of raw bytes from the base stream to the given buffer
/// </summary>
/// <param name="buffer"></param>
/// <param name="bytesToRead"></param>
/// <returns>The number of bytes read</returns>
public Task<int> ReadBytesAsync(byte[] buffer, int bytesToRead)
{
return stream.ReadAsync(buffer, 0, bytesToRead);
}
public void Dispose()
{
if (!disposed)
{
disposed = true;
BufferPool.ReturnBuffer(Buffer);
}
}
/// <summary>
/// Increase size of buffer and copy existing content to new buffer
/// </summary>
/// <param name="buffer"></param>
/// <param name="size"></param>
private void ResizeBuffer(ref byte[] buffer, long size)
{
var newBuffer = new byte[size];
System.Buffer.BlockCopy(buffer, 0, newBuffer, 0, buffer.Length);
buffer = newBuffer;
}
}
}
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Network
{
public class CustomBufferedPeekStream : IBufferedStream
{
private readonly CustomBufferedStream baseStream;
internal int Position { get; private set; }
public CustomBufferedPeekStream(CustomBufferedStream baseStream, int startPosition = 0)
{
this.baseStream = baseStream;
Position = startPosition;
}
internal int Available => baseStream.Available - Position;
bool IBufferedStream.DataAvailable => Available > 0;
internal async Task<bool> EnsureBufferLength(int length)
{
var val = await baseStream.PeekByteAsync(Position + length - 1);
return val != -1;
}
internal byte ReadByte()
{
return baseStream.PeekByteFromBuffer(Position++);
}
internal int ReadInt16()
{
int i1 = ReadByte();
int i2 = ReadByte();
return (i1 << 8) + i2;
}
internal int ReadInt24()
{
int i1 = ReadByte();
int i2 = ReadByte();
int i3 = ReadByte();
return (i1 << 16) + (i2 << 8) + i3;
}
internal byte[] ReadBytes(int length)
{
var buffer = new byte[length];
for (int i = 0; i < buffer.Length; i++)
{
buffer[i] = ReadByte();
}
return buffer;
}
Task<bool> IBufferedStream.FillBufferAsync()
{
return baseStream.FillBufferAsync();
}
byte IBufferedStream.ReadByteFromBuffer()
{
return ReadByte();
}
Task<int> IBufferedStream.ReadAsync(byte[] buffer, int offset, int count)
{
return baseStream.ReadAsync(buffer, offset, count);
}
}
}
This diff is collapsed.
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Network
{
public interface IBufferedStream
{
bool DataAvailable { get; }
Task<bool> FillBufferAsync();
byte ReadByteFromBuffer();
Task<int> ReadAsync(byte[] buffer, int offset, int count);
}
}
\ No newline at end of file
using StreamExtended.Network; using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
......
using StreamExtended; using System;
using StreamExtended.Network;
using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
...@@ -8,12 +6,14 @@ using System.Net.Security; ...@@ -8,12 +6,14 @@ using System.Net.Security;
using System.Net.Sockets; using System.Net.Sockets;
using System.Security.Authentication; using System.Security.Authentication;
using System.Threading.Tasks; using System.Threading.Tasks;
using StreamExtended.Helpers;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions; using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
using Titanium.Web.Proxy.Network.Tcp; using Titanium.Web.Proxy.Network.Tcp;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
...@@ -233,7 +233,12 @@ namespace Titanium.Web.Proxy ...@@ -233,7 +233,12 @@ namespace Titanium.Web.Proxy
var sslStream = new SslStream(clientStream); var sslStream = new SslStream(clientStream);
clientStream = new CustomBufferedStream(sslStream, BufferSize); clientStream = new CustomBufferedStream(sslStream, BufferSize);
string sniHostName = clientSslHelloInfo.Extensions?.FirstOrDefault(x => x.Name == "server_name")?.Data; string sniHostName = null;
if (clientSslHelloInfo.Extensions != null && clientSslHelloInfo.Extensions.TryGetValue("server_name", out var serverNameExtension))
{
sniHostName = serverNameExtension.Data;
}
string certName = HttpHelper.GetWildCardDomainName(sniHostName ?? endPoint.GenericCertificateName); string certName = HttpHelper.GetWildCardDomainName(sniHostName ?? endPoint.GenericCertificateName);
var certificate = CertificateManager.CreateCertificate(certName, false); var certificate = CertificateManager.CreateCertificate(certName, false);
...@@ -628,9 +633,25 @@ namespace Titanium.Web.Proxy ...@@ -628,9 +633,25 @@ namespace Titanium.Web.Proxy
if (args.HasMulipartEventSubscribers && request.IsMultipartFormData) if (args.HasMulipartEventSubscribers && request.IsMultipartFormData)
{ {
string boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType); string boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType);
args.OnMultipartRequestPartSent(boundary);
// todo long bytesToSend = args.WebSession.Request.ContentLength;
await args.ProxyClient.ClientStreamReader.CopyBytesToStream(postStream, args.WebSession.Request.ContentLength); while (bytesToSend > 0)
{
long read = await SendUntilBoundaryAsync(args.ProxyClient.ClientStream, postStream, bytesToSend, boundary);
if (read == 0)
{
break;
}
bytesToSend -= read;
if (bytesToSend > 0)
{
var headers = new HeaderCollection();
var stream = new CustomBufferedPeekStream(args.ProxyClient.ClientStream);
await HeaderParser.ReadHeaders(new CustomBinaryReader(stream, BufferSize), headers);
args.OnMultipartRequestPartSent(boundary, headers);
}
}
} }
else else
{ {
...@@ -644,5 +665,68 @@ namespace Titanium.Web.Proxy ...@@ -644,5 +665,68 @@ namespace Titanium.Web.Proxy
await args.ProxyClient.ClientStreamReader.CopyBytesToStreamChunked(postStream); await args.ProxyClient.ClientStreamReader.CopyBytesToStreamChunked(postStream);
} }
} }
/// <summary>
/// Read a line from the byte stream
/// </summary>
/// <returns></returns>
public async Task<long> SendUntilBoundaryAsync(CustomBufferedStream inputStream, CustomBufferedStream outputStream, long totalBytesToRead, string boundary)
{
int bufferDataLength = 0;
// try to use the thread static buffer
var buffer = BufferPool.GetBuffer(BufferSize);
int boundaryLength = boundary.Length + 4;
long bytesRead = 0;
while (bytesRead < totalBytesToRead && (inputStream.DataAvailable || await inputStream.FillBufferAsync()))
{
byte newChar = inputStream.ReadByteFromBuffer();
buffer[bufferDataLength] = newChar;
bufferDataLength++;
bytesRead++;
if (bufferDataLength >= boundaryLength)
{
int startIdx = bufferDataLength - boundaryLength;
if (buffer[startIdx] == '-' && buffer[startIdx + 1] == '-'
&& buffer[bufferDataLength - 2] == '\r' && buffer[bufferDataLength - 1] == '\n')
{
startIdx += 2;
bool ok = true;
for (int i = 0; i < boundary.Length; i++)
{
if (buffer[startIdx + i] != boundary[i])
{
ok = false;
break;
}
}
if (ok)
{
break;
}
}
}
if (bufferDataLength == buffer.Length)
{
//boundary is not longer than 70 bytes accounrding to the specification, so keeping the last 100 (minimum 74) bytes is enough
const int bytesToKeep = 100;
await outputStream.WriteAsync(buffer, 0, buffer.Length - bytesToKeep);
Buffer.BlockCopy(buffer, buffer.Length - bytesToKeep, buffer, 0, bytesToKeep);
bufferDataLength = bytesToKeep;
}
}
if (bytesRead > 0)
{
await outputStream.WriteAsync(buffer, 0, bufferDataLength);
}
return bytesRead;
}
} }
} }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy
{
public class ServerHelloInfo
{
private static readonly string[] compressions = {
"null",
"DEFLATE"
};
public int MajorVersion { get; set; }
public int MinorVersion { get; set; }
public byte[] Random { get; set; }
public DateTime Time
{
get
{
DateTime time = DateTime.MinValue;
if (Random.Length > 3)
{
time = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)
.AddSeconds(((uint)Random[3] << 24) + ((uint)Random[2] << 16) + ((uint)Random[1] << 8) + (uint)Random[0]).ToLocalTime();
}
return time;
}
}
public byte[] SessionId { get; set; }
public int CipherSuite { get; set; }
public byte CompressionMethod { get; set; }
internal int ServerHelloLength { get; set; }
internal int EntensionsStartPosition { get; set; }
public Dictionary<string, SslExtension> Extensions { get; set; }
private static string SslVersionToString(int major, int minor)
{
string str = "Unknown";
if (major == 3 && minor == 3)
str = "TLS/1.2";
else if (major == 3 && minor == 2)
str = "TLS/1.1";
else if (major == 3 && minor == 1)
str = "TLS/1.0";
else if (major == 3 && minor == 0)
str = "SSL/3.0";
else if (major == 2 && minor == 0)
str = "SSL/2.0";
return $"{major}.{minor} ({str})";
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine("A SSLv3-compatible ServerHello handshake was found. Titanium extracted the parameters below.");
sb.AppendLine();
sb.AppendLine($"Version: {SslVersionToString(MajorVersion, MinorVersion)}");
sb.AppendLine($"Random: {string.Join(" ", Random.Select(x => x.ToString("X2")))}");
sb.AppendLine($"\"Time\": {Time}");
sb.AppendLine($"SessionID: {string.Join(" ", SessionId.Select(x => x.ToString("X2")))}");
if (Extensions != null)
{
sb.AppendLine("Extensions:");
foreach (var extension in Extensions.Values.OrderBy(x => x.Position))
{
sb.AppendLine($"{extension.Name}: {extension.Data}");
}
}
string compression = compressions.Length > CompressionMethod
? compressions[CompressionMethod]
: $"unknown [0x{CompressionMethod:X2}]";
sb.AppendLine($"Compression: {compression}");
sb.Append("Cipher:");
if (!SslCiphers.Ciphers.TryGetValue(CipherSuite, out string cipherStr))
{
cipherStr = "unknown";
}
sb.AppendLine($"[0x{CipherSuite:X4}] {cipherStr}");
return sb.ToString();
}
}
}
\ No newline at end of file
This diff is collapsed.
using System.Collections.Generic;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
namespace Titanium.Web.Proxy
{
public class SslTools
{
public static async Task<bool> IsClientHello(CustomBufferedStream stream)
{
var clientHello = await PeekClientHello(stream);
return clientHello != null;
}
public static async Task<ClientHelloInfo> PeekClientHello(CustomBufferedStream clientStream)
{
//detects the HTTPS ClientHello message as it is described in the following url:
//https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format
int recordType = await clientStream.PeekByteAsync(0);
if (recordType == 0x80)
{
var peekStream = new CustomBufferedPeekStream(clientStream, 1);
//SSL 2
int length = peekStream.ReadByte();
if (length < 9)
{
// Message body too short.
return null;
}
if (peekStream.ReadByte() != 0x01)
{
// should be ClientHello
return null;
}
int majorVersion = clientStream.ReadByte();
int minorVersion = clientStream.ReadByte();
return new ClientHelloInfo();
}
else if (recordType == 0x16)
{
var peekStream = new CustomBufferedPeekStream(clientStream, 1);
//should contain at least 43 bytes
// 2 version + 2 length + 1 type + 3 length(?) + 2 version + 32 random + 1 sessionid length
if (!await peekStream.EnsureBufferLength(43))
{
return null;
}
//SSL 3.0 or TLS 1.0, 1.1 and 1.2
int majorVersion = peekStream.ReadByte();
int minorVersion = peekStream.ReadByte();
int length = peekStream.ReadInt16();
if (peekStream.ReadByte() != 0x01)
{
// should be ClientHello
return null;
}
length = peekStream.ReadInt24();
majorVersion = peekStream.ReadByte();
minorVersion = peekStream.ReadByte();
byte[] random = peekStream.ReadBytes(32);
length = peekStream.ReadByte();
// sessionid + 2 ciphersData length
if (!await peekStream.EnsureBufferLength(length + 2))
{
return null;
}
byte[] sessionId = peekStream.ReadBytes(length);
length = peekStream.ReadInt16();
// ciphersData + compressionData length
if (!await peekStream.EnsureBufferLength(length + 1))
{
return null;
}
byte[] ciphersData = peekStream.ReadBytes(length);
int[] ciphers = new int[ciphersData.Length / 2];
for (int i = 0; i < ciphers.Length; i++)
{
ciphers[i] = (ciphersData[2 * i] << 8) + ciphersData[2 * i + 1];
}
length = peekStream.ReadByte();
if (length < 1)
{
return null;
}
// compressionData
if (!await peekStream.EnsureBufferLength(length))
{
return null;
}
byte[] compressionData = peekStream.ReadBytes(length);
int extenstionsStartPosition = peekStream.Position;
var extensions = await ReadExtensions(majorVersion, minorVersion, peekStream);
var clientHelloInfo = new ClientHelloInfo
{
MajorVersion = majorVersion,
MinorVersion = minorVersion,
Random = random,
SessionId = sessionId,
Ciphers = ciphers,
CompressionData = compressionData,
ClientHelloLength = peekStream.Position,
EntensionsStartPosition = extenstionsStartPosition,
Extensions = extensions,
};
return clientHelloInfo;
}
return null;
}
private static async Task<Dictionary<string, SslExtension>> ReadExtensions(int majorVersion, int minorVersion, CustomBufferedPeekStream peekStream)
{
Dictionary<string, SslExtension> extensions = null;
if (majorVersion > 3 || majorVersion == 3 && minorVersion >= 1)
{
if (await peekStream.EnsureBufferLength(2))
{
int extensionsLength = peekStream.ReadInt16();
if (await peekStream.EnsureBufferLength(extensionsLength))
{
extensions = new Dictionary<string, SslExtension>();
int idx = 0;
while (extensionsLength > 3)
{
int id = peekStream.ReadInt16();
int length = peekStream.ReadInt16();
byte[] data = peekStream.ReadBytes(length);
var extension = SslExtensions.GetExtension(id, data, idx++);
extensions[extension.Name] = extension;
extensionsLength -= 4 + length;
}
}
}
}
return extensions;
}
public static async Task<bool> IsServerHello(CustomBufferedStream stream)
{
var serverHello = await PeekServerHello(stream);
return serverHello != null;
}
public static async Task<ServerHelloInfo> PeekServerHello(CustomBufferedStream serverStream)
{
//detects the HTTPS ClientHello message as it is described in the following url:
//https://stackoverflow.com/questions/3897883/how-to-detect-an-incoming-ssl-https-handshake-ssl-wire-format
int recordType = await serverStream.PeekByteAsync(0);
if (recordType == 0x80)
{
// copied from client hello, not tested. SSL2 is deprecated
var peekStream = new CustomBufferedPeekStream(serverStream, 1);
//SSL 2
int length = peekStream.ReadByte();
if (length < 9)
{
// Message body too short.
return null;
}
if (peekStream.ReadByte() != 0x02)
{
// should be ServerHello
return null;
}
int majorVersion = serverStream.ReadByte();
int minorVersion = serverStream.ReadByte();
return new ServerHelloInfo();
}
else if (recordType == 0x16)
{
var peekStream = new CustomBufferedPeekStream(serverStream, 1);
//should contain at least 43 bytes
// 2 version + 2 length + 1 type + 3 length(?) + 2 version + 32 random + 1 sessionid length
if (!await peekStream.EnsureBufferLength(43))
{
return null;
}
//SSL 3.0 or TLS 1.0, 1.1 and 1.2
int majorVersion = peekStream.ReadByte();
int minorVersion = peekStream.ReadByte();
int length = peekStream.ReadInt16();
if (peekStream.ReadByte() != 0x02)
{
// should be ServerHello
return null;
}
length = peekStream.ReadInt24();
majorVersion = peekStream.ReadByte();
minorVersion = peekStream.ReadByte();
byte[] random = peekStream.ReadBytes(32);
length = peekStream.ReadByte();
// sessionid + cipherSuite + compressionMethod
if (!await peekStream.EnsureBufferLength(length + 2 + 1))
{
return null;
}
byte[] sessionId = peekStream.ReadBytes(length);
int cipherSuite = peekStream.ReadInt16();
byte compressionMethod = peekStream.ReadByte();
int extenstionsStartPosition = peekStream.Position;
var extensions = await ReadExtensions(majorVersion, minorVersion, peekStream);
//var rawBytes = new CustomBufferedPeekStream(serverStream).ReadBytes(peekStream.Position);
var serverHelloInfo = new ServerHelloInfo
{
MajorVersion = majorVersion,
MinorVersion = minorVersion,
Random = random,
SessionId = sessionId,
CipherSuite = cipherSuite,
CompressionMethod = compressionMethod,
ServerHelloLength = peekStream.Position,
EntensionsStartPosition = extenstionsStartPosition,
Extensions = extensions,
};
return serverHelloInfo;
}
return null;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment