Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.
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
2 changes: 1 addition & 1 deletion Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal class CustomBinaryReader : IDisposable
private static readonly ConcurrentQueue<byte[]> buffers
= new ConcurrentQueue<byte[]>();

private volatile bool disposed = false;
private volatile bool disposed;

internal CustomBinaryReader(CustomBufferedStream stream, int bufferSize)
{
Expand Down
3 changes: 1 addition & 2 deletions Titanium.Web.Proxy/ProxyServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,7 @@ public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint)
#if !DEBUG
firefoxProxySettingsManager.AddFirefox();
#endif
Console.WriteLine("Set endpoint at Ip {0} and port: {1} as System HTTPS Proxy",
endPoint.IpAddress, endPoint.Port);
Console.WriteLine("Set endpoint at Ip {0} and port: {1} as System HTTPS Proxy", endPoint.IpAddress, endPoint.Port);
}

/// <summary>
Expand Down
149 changes: 47 additions & 102 deletions Titanium.Web.Proxy/RequestHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpCli
//Successfully managed to authenticate the client using the fake certificate
await sslStream.AuthenticateAsServerAsync(certificate, false,
SupportedSslProtocols, false);

//HTTPS server created - we can now decrypt the client's traffic
clientStream = new CustomBufferedStream(sslStream, BufferSize);

Expand All @@ -138,6 +139,7 @@ await sslStream.AuthenticateAsServerAsync(certificate, false,
{
//Siphon out CONNECT request headers
await clientStreamReader.ReadAndIgnoreAllLinesAsync();

//write back successfull CONNECT response
await WriteConnectResponse(clientStreamWriter, version);

Expand Down Expand Up @@ -172,8 +174,7 @@ await TcpHelper.SendRaw(this,
//So for HTTPS requests we would start SSL negotiation right away without expecting a CONNECT request from client
private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcpClient)
{
var disposed = false;

bool disposed = false;
var clientStream = new CustomBufferedStream(tcpClient.GetStream(), BufferSize);

clientStream.ReadTimeout = ConnectionTimeOutSeconds * 1000;
Expand All @@ -182,52 +183,39 @@ private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcp
CustomBinaryReader clientStreamReader = null;
StreamWriter clientStreamWriter = null;

if (endPoint.EnableSsl)
try
{
var sslStream = new SslStream(clientStream, true);
if (endPoint.EnableSsl)
{
var sslStream = new SslStream(clientStream, true);
clientStream = new CustomBufferedStream(sslStream, BufferSize);

//implement in future once SNI supported by SSL stream, for now use the same certificate
var certificate = CertificateManager.CreateCertificate(endPoint.GenericCertificateName, false);
//implement in future once SNI supported by SSL stream, for now use the same certificate
var certificate = CertificateManager.CreateCertificate(endPoint.GenericCertificateName, false);

try
{
//Successfully managed to authenticate the client using the fake certificate
await sslStream.AuthenticateAsServerAsync(certificate, false,
SslProtocols.Tls, false);

clientStream = new CustomBufferedStream(sslStream, BufferSize);
clientStreamReader = new CustomBinaryReader(clientStream, BufferSize);
clientStreamWriter = new StreamWriter(clientStream) { NewLine = ProxyConstants.NewLine };
//HTTPS server created - we can now decrypt the client's traffic
}
catch (Exception)
{
sslStream.Dispose();

Dispose(sslStream,
clientStreamReader,
clientStreamWriter, null);

disposed = true;
return;
}
}
else
{
clientStreamReader = new CustomBinaryReader(clientStream, BufferSize);
clientStreamWriter = new StreamWriter(clientStream) { NewLine = ProxyConstants.NewLine };
}

//now read the request line
var httpCmd = await clientStreamReader.ReadLineAsync();

//Now create the request
disposed = await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
endPoint.EnableSsl ? endPoint.GenericCertificateName : null, endPoint, null);
//now read the request line
var httpCmd = await clientStreamReader.ReadLineAsync();

if (!disposed)
//Now create the request
disposed = await HandleHttpSessionRequest(tcpClient, httpCmd, clientStream, clientStreamReader, clientStreamWriter,
endPoint.EnableSsl ? endPoint.GenericCertificateName : null, endPoint, null);
}
finally
{
Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
if (!disposed)
{
Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
}
}
}

Expand Down Expand Up @@ -271,21 +259,18 @@ private async Task<TcpConnection> GetServerConnection(
}


private async Task<bool> HandleHttpSessionRequestInternal(TcpConnection connection,
SessionEventArgs args, bool closeConnection)
private async Task<bool> HandleHttpSessionRequestInternal(TcpConnection connection, SessionEventArgs args, bool closeConnection)
{
bool disposed = false;
bool keepAlive = false;

try
{
args.WebSession.Request.RequestLocked = true;

//If request was cancelled by user then dispose the client
if (args.WebSession.Request.CancelRequest)
{
Dispose(args.ProxyClient.ClientStream,
args.ProxyClient.ClientStreamReader,
args.ProxyClient.ClientStreamWriter,
args.WebSession.ServerConnection);

return true;
}

Expand Down Expand Up @@ -350,50 +335,42 @@ await WriteResponseStatus(args.WebSession.Response.HttpVersion, "417",
//If not expectation failed response was returned by server then parse response
if (!args.WebSession.Request.ExpectationFailed)
{
var disposed = await HandleHttpSessionResponse(args);
disposed = await HandleHttpSessionResponse(args);

//already disposed inside above method
if (disposed)
{
return disposed;
return true;
}
}

//if connection is closing exit
if (args.WebSession.Response.ResponseKeepAlive == false)
{
Dispose(args.ProxyClient.ClientStream,
args.ProxyClient.ClientStreamReader,
args.ProxyClient.ClientStreamWriter,
args.WebSession.ServerConnection);

return true;
}

if (!closeConnection)
{
keepAlive = true;
return false;
}
}
catch (Exception e)
{
ExceptionFunc(new ProxyHttpException("Error occured whilst handling session request (internal)", e, args));

Dispose(args.ProxyClient.ClientStream,
args.ProxyClient.ClientStreamReader,
args.ProxyClient.ClientStreamWriter,
args.WebSession.ServerConnection);

return true;
}

if (closeConnection)
finally
{
//dispose
Dispose(args.ProxyClient.ClientStream,
args.ProxyClient.ClientStreamReader,
args.ProxyClient.ClientStreamWriter,
args.WebSession.ServerConnection);

return true;
if (!disposed && !keepAlive)
{
//dispose
Dispose(args.ProxyClient.ClientStream, args.ProxyClient.ClientStreamReader, args.ProxyClient.ClientStreamWriter, args.WebSession.ServerConnection);
}
}

return false;
return true;
}

/// <summary>
Expand All @@ -412,7 +389,7 @@ private async Task<bool> HandleHttpSessionRequest(TcpClient client, string httpC
CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string httpsHostName,
ProxyEndPoint endPoint, List<HttpHeader> connectHeaders)
{
var disposed = false;
bool disposed = false;

TcpConnection connection = null;

Expand All @@ -422,12 +399,6 @@ private async Task<bool> HandleHttpSessionRequest(TcpClient client, string httpC
{
if (string.IsNullOrEmpty(httpCmd))
{
Dispose(clientStream,
clientStreamReader,
clientStreamWriter,
connection);

disposed = true;
break;
}

Expand Down Expand Up @@ -489,12 +460,6 @@ private async Task<bool> HandleHttpSessionRequest(TcpClient client, string httpC
await CheckAuthorization(clientStreamWriter,
args.WebSession.Request.RequestHeaders.Values) == false)
{
Dispose(clientStream,
clientStreamReader,
clientStreamWriter,
connection);

disposed = true;
break;
}

Expand All @@ -515,12 +480,6 @@ await TcpHelper.SendRaw(this,
httpCmd, httpVersion, args.WebSession.Request.RequestHeaders, args.IsHttps,
clientStream, tcpConnectionFactory);

Dispose(clientStream,
clientStreamReader,
clientStreamWriter,
connection);

disposed = true;
break;
}

Expand All @@ -540,24 +499,12 @@ await TcpHelper.SendRaw(this,

if (args.WebSession.Request.CancelRequest)
{
Dispose(clientStream,
clientStreamReader,
clientStreamWriter,
connection);

disposed = true;
break;
}

//if connection is closing exit
if (args.WebSession.Response.ResponseKeepAlive == false)
{
Dispose(clientStream,
clientStreamReader,
clientStreamWriter,
connection);

disposed = true;
break;
}

Expand All @@ -567,18 +514,16 @@ await TcpHelper.SendRaw(this,
catch (Exception e)
{
ExceptionFunc(new ProxyHttpException("Error occured whilst handling session request", e, args));

Dispose(clientStream,
clientStreamReader,
clientStreamWriter,
connection);

disposed = true;
break;
}
}

return disposed;
if (!disposed)
{
Dispose(clientStream, clientStreamReader, clientStreamWriter, connection);
}

return true;
}

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions Titanium.Web.Proxy/ResponseHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ private async Task<bool> HandleHttpSessionResponse(SessionEventArgs args)
}

var connection = await GetServerConnection(args);
var result = await HandleHttpSessionRequestInternal(null, args, true);
return result;
var disposed = await HandleHttpSessionRequestInternal(null, args, true);
return disposed;
}

args.WebSession.Response.ResponseLocked = true;
Expand Down