Commit 903a5958 authored by Honfika's avatar Honfika

Stream disposing fix, SslStream should dispose the inner stream (true parameter removed)

parent d837e87b
...@@ -146,14 +146,6 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -146,14 +146,6 @@ namespace Titanium.Web.Proxy.Helpers
return baseStream.BeginWrite(buffer, offset, count, callback, state); return baseStream.BeginWrite(buffer, offset, count, callback, state);
} }
/// <summary>
/// Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream. Instead of calling this method, ensure that the stream is properly disposed.
/// </summary>
public override void Close()
{
baseStream.Close();
}
/// <summary> /// <summary>
/// Asynchronously reads the bytes from the current stream and writes them to another stream, using a specified buffer size and cancellation token. /// Asynchronously reads the bytes from the current stream and writes them to another stream, using a specified buffer size and cancellation token.
/// </summary> /// </summary>
......
...@@ -213,7 +213,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -213,7 +213,7 @@ namespace Titanium.Web.Proxy.Helpers
var tcpConnection = await tcpConnectionFactory.CreateClient(server, var tcpConnection = await tcpConnectionFactory.CreateClient(server,
remoteHostName, remotePort, remoteHostName, remotePort,
httpVersion, isHttps, httpVersion, isHttps,
null, null, clientStream); null, null);
try try
{ {
......
...@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </summary> /// </summary>
internal Version Version { get; set; } internal Version Version { get; set; }
internal TcpClient TcpClient { get; set; } internal TcpClient TcpClient { private get; set; }
/// <summary> /// <summary>
/// used to read lines from server /// used to read lines from server
...@@ -54,7 +54,6 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -54,7 +54,6 @@ namespace Titanium.Web.Proxy.Network.Tcp
public void Dispose() public void Dispose()
{ {
Stream?.Close(); Stream?.Close();
Stream?.Dispose();
StreamReader?.Dispose(); StreamReader?.Dispose();
......
...@@ -28,17 +28,12 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -28,17 +28,12 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="isHttps"></param> /// <param name="isHttps"></param>
/// <param name="externalHttpProxy"></param> /// <param name="externalHttpProxy"></param>
/// <param name="externalHttpsProxy"></param> /// <param name="externalHttpsProxy"></param>
/// <param name="clientStream"></param>
/// <returns></returns> /// <returns></returns>
internal async Task<TcpConnection> CreateClient(ProxyServer server, internal async Task<TcpConnection> CreateClient(ProxyServer server,
string remoteHostName, int remotePort, Version httpVersion, string remoteHostName, int remotePort, Version httpVersion,
bool isHttps, bool isHttps,
ExternalProxy externalHttpProxy, ExternalProxy externalHttpsProxy, ExternalProxy externalHttpProxy, ExternalProxy externalHttpsProxy)
Stream clientStream)
{ {
TcpClient client;
CustomBufferedStream stream;
bool useHttpProxy = false; bool useHttpProxy = false;
//check if external proxy is set for HTTP //check if external proxy is set for HTTP
if (!isHttps && externalHttpProxy != null if (!isHttps && externalHttpProxy != null
...@@ -71,88 +66,86 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -71,88 +66,86 @@ namespace Titanium.Web.Proxy.Network.Tcp
} }
} }
if (isHttps) TcpClient client = null;
{ CustomBufferedStream stream = null;
SslStream sslStream = null;
//If this proxy uses another external proxy then create a tunnel request for HTTPS connections try
if (useHttpsProxy) {
if (isHttps)
{ {
client = new TcpClient(server.UpStreamEndPoint); //If this proxy uses another external proxy then create a tunnel request for HTTPS connections
await client.ConnectAsync(externalHttpsProxy.HostName, externalHttpsProxy.Port); if (useHttpsProxy)
stream = new CustomBufferedStream(client.GetStream(), server.BufferSize);
using (var writer = new StreamWriter(stream, Encoding.ASCII, server.BufferSize, true) { NewLine = ProxyConstants.NewLine })
{ {
await writer.WriteLineAsync($"CONNECT {remoteHostName}:{remotePort} HTTP/{httpVersion}"); client = new TcpClient(server.UpStreamEndPoint);
await writer.WriteLineAsync($"Host: {remoteHostName}:{remotePort}"); await client.ConnectAsync(externalHttpsProxy.HostName, externalHttpsProxy.Port);
await writer.WriteLineAsync("Connection: Keep-Alive"); stream = new CustomBufferedStream(client.GetStream(), server.BufferSize);
if (!string.IsNullOrEmpty(externalHttpsProxy.UserName) && externalHttpsProxy.Password != null) using (var writer = new StreamWriter(stream, Encoding.ASCII, server.BufferSize, true) { NewLine = ProxyConstants.NewLine })
{ {
await writer.WriteLineAsync("Proxy-Connection: keep-alive"); await writer.WriteLineAsync($"CONNECT {remoteHostName}:{remotePort} HTTP/{httpVersion}");
await writer.WriteLineAsync("Proxy-Authorization" + ": Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(externalHttpsProxy.UserName + ":" + externalHttpsProxy.Password))); await writer.WriteLineAsync($"Host: {remoteHostName}:{remotePort}");
await writer.WriteLineAsync("Connection: Keep-Alive");
if (!string.IsNullOrEmpty(externalHttpsProxy.UserName) && externalHttpsProxy.Password != null)
{
await writer.WriteLineAsync("Proxy-Connection: keep-alive");
await writer.WriteLineAsync("Proxy-Authorization" + ": Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(externalHttpsProxy.UserName + ":" + externalHttpsProxy.Password)));
}
await writer.WriteLineAsync();
await writer.FlushAsync();
writer.Close();
} }
await writer.WriteLineAsync();
await writer.FlushAsync();
writer.Close();
}
using (var reader = new CustomBinaryReader(stream, server.BufferSize)) using (var reader = new CustomBinaryReader(stream, server.BufferSize))
{
var result = await reader.ReadLineAsync();
if (!new[] { "200 OK", "connection established" }.Any(s => result.ContainsIgnoreCase(s)))
{ {
throw new Exception("Upstream proxy failed to create a secure tunnel"); var result = await reader.ReadLineAsync();
}
if (!new[] { "200 OK", "connection established" }.Any(s => result.ContainsIgnoreCase(s)))
{
throw new Exception("Upstream proxy failed to create a secure tunnel");
}
await reader.ReadAndIgnoreAllLinesAsync(); await reader.ReadAndIgnoreAllLinesAsync();
}
}
else
{
client = new TcpClient(server.UpStreamEndPoint);
await client.ConnectAsync(remoteHostName, remotePort);
stream = new CustomBufferedStream(client.GetStream(), server.BufferSize);
} }
}
else
{
client = new TcpClient(server.UpStreamEndPoint);
await client.ConnectAsync(remoteHostName, remotePort);
stream = new CustomBufferedStream(client.GetStream(), server.BufferSize);
}
try var sslStream = new SslStream(stream, false, server.ValidateServerCertificate, server.SelectClientCertificate);
{ stream = new CustomBufferedStream(sslStream, server.BufferSize);
sslStream = new SslStream(stream, true, server.ValidateServerCertificate,
server.SelectClientCertificate);
await sslStream.AuthenticateAsClientAsync(remoteHostName, null, server.SupportedSslProtocols, server.CheckCertificateRevocation); await sslStream.AuthenticateAsClientAsync(remoteHostName, null, server.SupportedSslProtocols, server.CheckCertificateRevocation);
stream = new CustomBufferedStream(sslStream, server.BufferSize);
} }
catch else
{ {
sslStream?.Close(); if (useHttpProxy)
sslStream?.Dispose(); {
client = new TcpClient(server.UpStreamEndPoint);
throw; await client.ConnectAsync(externalHttpProxy.HostName, externalHttpProxy.Port);
stream = new CustomBufferedStream(client.GetStream(), server.BufferSize);
}
else
{
client = new TcpClient(server.UpStreamEndPoint);
await client.ConnectAsync(remoteHostName, remotePort);
stream = new CustomBufferedStream(client.GetStream(), server.BufferSize);
}
} }
client.ReceiveTimeout = server.ConnectionTimeOutSeconds * 1000;
client.SendTimeout = server.ConnectionTimeOutSeconds * 1000;
} }
else catch (Exception)
{ {
if (useHttpProxy) stream?.Dispose();
{ client?.Close();
client = new TcpClient(server.UpStreamEndPoint); throw;
await client.ConnectAsync(externalHttpProxy.HostName, externalHttpProxy.Port);
stream = new CustomBufferedStream(client.GetStream(), server.BufferSize);
}
else
{
client = new TcpClient(server.UpStreamEndPoint);
await client.ConnectAsync(remoteHostName, remotePort);
stream = new CustomBufferedStream(client.GetStream(), server.BufferSize);
}
} }
client.ReceiveTimeout = server.ConnectionTimeOutSeconds * 1000;
client.SendTimeout = server.ConnectionTimeOutSeconds * 1000;
Interlocked.Increment(ref server.serverConnectionCount); Interlocked.Increment(ref server.serverConnectionCount);
return new TcpConnection return new TcpConnection
......
...@@ -111,7 +111,7 @@ namespace Titanium.Web.Proxy ...@@ -111,7 +111,7 @@ namespace Titanium.Web.Proxy
try try
{ {
sslStream = new SslStream(clientStream, true); sslStream = new SslStream(clientStream);
var certificate = endPoint.GenericCertificate ?? var certificate = endPoint.GenericCertificate ??
CertificateManager.CreateCertificate(httpRemoteUri.Host, false); CertificateManager.CreateCertificate(httpRemoteUri.Host, false);
...@@ -191,7 +191,7 @@ namespace Titanium.Web.Proxy ...@@ -191,7 +191,7 @@ namespace Titanium.Web.Proxy
{ {
if (endPoint.EnableSsl) if (endPoint.EnableSsl)
{ {
var sslStream = new SslStream(clientStream, true); var sslStream = new SslStream(clientStream);
clientStream = new CustomBufferedStream(sslStream, BufferSize); clientStream = new CustomBufferedStream(sslStream, BufferSize);
//implement in future once SNI supported by SSL stream, for now use the same certificate //implement in future once SNI supported by SSL stream, for now use the same certificate
...@@ -542,8 +542,7 @@ namespace Titanium.Web.Proxy ...@@ -542,8 +542,7 @@ namespace Titanium.Web.Proxy
args.WebSession.Request.HttpVersion, args.WebSession.Request.HttpVersion,
args.IsHttps, args.IsHttps,
customUpStreamHttpProxy ?? UpStreamHttpProxy, customUpStreamHttpProxy ?? UpStreamHttpProxy,
customUpStreamHttpsProxy ?? UpStreamHttpsProxy, customUpStreamHttpsProxy ?? UpStreamHttpsProxy);
args.ProxyClient.ClientStream);
} }
......
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