Commit fe4d5ee9 authored by titanium007's avatar titanium007

Expose only properties that are safer to user

parent 214be692
...@@ -76,11 +76,11 @@ namespace Titanium.Web.Proxy.Test ...@@ -76,11 +76,11 @@ namespace Titanium.Web.Proxy.Test
if (index >= 0) if (index >= 0)
{ {
string URL = e.Decode(); string URL = e.GetRequestHtmlBody();
if (_lastURL != URL) if (_lastURL != URL)
{ {
OnChanged(new VisitedEventArgs() { hostname = e.Hostname, URL = URL, remoteIP = e.ipAddress, remotePort = e.Port }); OnChanged(new VisitedEventArgs() { hostname = e.RequestHostname, URL = URL, remoteIP = e.ClientIpAddress, remotePort = e.ClientPort });
} }
...@@ -106,7 +106,7 @@ namespace Titanium.Web.Proxy.Test ...@@ -106,7 +106,7 @@ namespace Titanium.Web.Proxy.Test
string c = e.ServerResponse.GetResponseHeader("X-Requested-With"); string c = e.ServerResponse.GetResponseHeader("X-Requested-With");
if (e.ServerResponse.GetResponseHeader("X-Requested-With") == "") if (e.ServerResponse.GetResponseHeader("X-Requested-With") == "")
{ {
e.GetResponseBody(); string responseHtmlBody = e.GetResponseHtmlBody();
string functioname = "fr" + RandomString(10); string functioname = "fr" + RandomString(10);
string VisitedURL = RandomString(5); string VisitedURL = RandomString(5);
...@@ -116,10 +116,10 @@ namespace Titanium.Web.Proxy.Test ...@@ -116,10 +116,10 @@ namespace Titanium.Web.Proxy.Test
string RandomLastRequest = RandomString(10); string RandomLastRequest = RandomString(10);
string LocalRequest; string LocalRequest;
if (e.IsSecure) if (e.IsSSLRequest)
LocalRequest = "https://" + e.Hostname + "/" + RandomURLEnding; LocalRequest = "https://" + e.RequestHostname + "/" + RandomURLEnding;
else else
LocalRequest = "http://" + e.Hostname + "/" + RandomURLEnding; LocalRequest = "http://" + e.RequestHostname + "/" + RandomURLEnding;
string script = "var " + RandomLastRequest + " = null;" + string script = "var " + RandomLastRequest + " = null;" +
"if(window.top==self) { " + "\n" + "if(window.top==self) { " + "\n" +
...@@ -135,13 +135,13 @@ namespace Titanium.Web.Proxy.Test ...@@ -135,13 +135,13 @@ namespace Titanium.Web.Proxy.Test
RequestVariable + ".open(\"POST\",\"" + LocalRequest + "\", true); " + "\n" + RequestVariable + ".open(\"POST\",\"" + LocalRequest + "\", true); " + "\n" +
RequestVariable + ".send(" + VisitedURL + ");} " + RandomLastRequest + " = " + VisitedURL + "}"; RequestVariable + ".send(" + VisitedURL + ");} " + RandomLastRequest + " = " + VisitedURL + "}";
string response = e.ResponseString;
Regex RE = new Regex("</body>", RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.Multiline); Regex RE = new Regex("</body>", RegexOptions.RightToLeft | RegexOptions.IgnoreCase | RegexOptions.Multiline);
string replaced = RE.Replace(response, "<script type =\"text/javascript\">" + script + "</script></body>", 1); string modifiedResponseHtmlBody = RE.Replace(responseHtmlBody, "<script type =\"text/javascript\">" + script + "</script></body>", 1);
if (replaced.Length != response.Length) if (modifiedResponseHtmlBody.Length != responseHtmlBody.Length)
{ {
e.ResponseString = replaced; e.SetRequestHtmlBody(modifiedResponseHtmlBody);
_URLList.Add(RandomURLEnding); _URLList.Add(RandomURLEnding);
} }
......
...@@ -9,84 +9,70 @@ namespace Titanium.Web.Proxy.Models ...@@ -9,84 +9,70 @@ namespace Titanium.Web.Proxy.Models
{ {
public class SessionEventArgs : EventArgs public class SessionEventArgs : EventArgs
{ {
public string RequestURL { get; set; } public string RequestURL { get; set; }
public string Hostname { get; set; } public string RequestHostname { get; set; }
public CustomBinaryReader ClientStreamReader { get; set; }
public string ResponseString { get; set; } public bool IsSSLRequest { get; set; }
public int RequestLength { get; set; }
public Stream ClientStream { get; set; } public int ClientPort { get; set; }
public Version HttpVersion { get; set; } public IPAddress ClientIpAddress { get; set; }
public bool IsAlive { get; set; }
public bool Cancel { get; set; }
public bool IsSecure { get; set; }
public int Port { get; set; }
private int BUFFER_SIZE;
public HttpWebResponse ServerResponse { get; set; }
public Stream ServerResponseStream { get; set; }
public HttpWebRequest ProxyRequest { get; set; } public HttpWebRequest ProxyRequest { get; set; }
public Encoding Encoding { get; set; } public HttpWebResponse ServerResponse { get; set; }
public bool WasModified { get; set; }
public System.Threading.ManualResetEvent FinishedRequestEvent { get; set; }
public string UpgradeProtocol { get; set; } internal int BUFFER_SIZE;
internal int RequestLength { get; set; }
internal Version RequestHttpVersion { get; set; }
internal bool RequestIsAlive { get; set; }
internal bool CancelRequest { get; set; }
internal CustomBinaryReader ClientStreamReader { get; set; }
internal Stream ClientStream { get; set; }
internal Stream ServerResponseStream { get; set; }
internal Encoding Encoding { get; set; }
internal bool WasModified { get; set; }
internal System.Threading.ManualResetEvent FinishedRequestEvent { get; set; }
internal string UpgradeProtocol { get; set; }
internal string RequestHtmlBody { get; set; }
internal string ResponseHtmlBody { get; set; }
public SessionEventArgs(int BufferSize) public SessionEventArgs(int BufferSize)
{ {
BUFFER_SIZE = BufferSize; BUFFER_SIZE = BufferSize;
} }
public string Decode() public string GetRequestHtmlBody()
{ {
if (RequestHtmlBody == null)
{
int bytesRead;
int totalBytesRead = 0;
MemoryStream mw = new MemoryStream();
var buffer = ClientStreamReader.ReadBytes(RequestLength);
while (totalBytesRead < RequestLength && (bytesRead = buffer.Length) > 0)
{
totalBytesRead += bytesRead;
mw.Write(buffer, 0, bytesRead);
int bytesRead; }
int totalBytesRead = 0;
MemoryStream mw = new MemoryStream();
var buffer = ClientStreamReader.ReadBytes(RequestLength);
while (totalBytesRead < RequestLength && (bytesRead = buffer.Length) > 0)
{
totalBytesRead += bytesRead;
mw.Write(buffer, 0, bytesRead);
mw.Close();
RequestHtmlBody = Encoding.Default.GetString(mw.ToArray());
} }
return RequestHtmlBody;
mw.Close();
return Encoding.Default.GetString(mw.ToArray());
} }
public void Ok(string Html) public void SetRequestHtmlBody(string Body)
{ {
this.RequestHtmlBody = Body;
if (Html == null)
Html = string.Empty;
var result = Encoding.Default.GetBytes(Html);
StreamWriter connectStreamWriter = new StreamWriter(ClientStream);
var s = String.Format("HTTP/{0}.{1} {2} {3}", HttpVersion.Major, HttpVersion.Minor, 200, "Ok");
connectStreamWriter.WriteLine(s);
connectStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString()));
connectStreamWriter.WriteLine("content-length: " + result.Length);
connectStreamWriter.WriteLine("Cache-Control: no-cache, no-store, must-revalidate");
connectStreamWriter.WriteLine("Pragma: no-cache");
connectStreamWriter.WriteLine("Expires: 0");
if (IsAlive)
{
connectStreamWriter.WriteLine("Connection: Keep-Alive");
}
else
connectStreamWriter.WriteLine("Connection: close");
connectStreamWriter.WriteLine();
connectStreamWriter.Flush();
ClientStream.Write(result, 0, result.Length);
Cancel = true;
} }
public void GetResponseBody() public string GetResponseHtmlBody()
{ {
if (ResponseString == null) if (ResponseHtmlBody == null)
{ {
Encoding = Encoding.GetEncoding(ServerResponse.CharacterSet); Encoding = Encoding.GetEncoding(ServerResponse.CharacterSet);
...@@ -110,9 +96,16 @@ namespace Titanium.Web.Proxy.Models ...@@ -110,9 +96,16 @@ namespace Titanium.Web.Proxy.Models
ResponseData = DecodeData(ServerResponseStream, Encoding); ResponseData = DecodeData(ServerResponseStream, Encoding);
break; break;
} }
ResponseString = ResponseData; ResponseHtmlBody = ResponseData;
WasModified = true; WasModified = true;
} }
return ResponseHtmlBody;
}
public void SetResponseHtmlBody(string Body)
{
this.ResponseHtmlBody = Body;
} }
//stream reader not recomended for images //stream reader not recomended for images
private string DecodeData(Stream ResponseStream, Encoding e) private string DecodeData(Stream ResponseStream, Encoding e)
...@@ -122,12 +115,45 @@ namespace Titanium.Web.Proxy.Models ...@@ -122,12 +115,45 @@ namespace Titanium.Web.Proxy.Models
} }
public void Ok(string Html)
{
if (Html == null)
Html = string.Empty;
var result = Encoding.Default.GetBytes(Html);
StreamWriter connectStreamWriter = new StreamWriter(ClientStream);
var s = String.Format("HTTP/{0}.{1} {2} {3}", RequestHttpVersion.Major, RequestHttpVersion.Minor, 200, "Ok");
connectStreamWriter.WriteLine(s);
connectStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString()));
connectStreamWriter.WriteLine("content-length: " + result.Length);
connectStreamWriter.WriteLine("Cache-Control: no-cache, no-store, must-revalidate");
connectStreamWriter.WriteLine("Pragma: no-cache");
connectStreamWriter.WriteLine("Expires: 0");
if (RequestIsAlive)
{
connectStreamWriter.WriteLine("Connection: Keep-Alive");
}
else
connectStreamWriter.WriteLine("Connection: close");
connectStreamWriter.WriteLine();
connectStreamWriter.Flush();
ClientStream.Write(result, 0, result.Length);
CancelRequest = true;
}
public IPAddress ipAddress { get; set; }
} }
} }
\ No newline at end of file
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Net.Security; using System.Net.Security;
using System.Security.Authentication; using System.Security.Authentication;
using System.Net.Sockets; using System.Net.Sockets;
using System.Diagnostics; using System.Diagnostics;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Reflection; using System.Reflection;
using Titanium.Web.Proxy.Helpers; using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy namespace Titanium.Web.Proxy
{ {
partial class ProxyServer partial class ProxyServer
{ {
private static void HandleClientRequest(TcpClient Client) private static void HandleClientRequest(TcpClient Client)
{ {
string connectionGroup = null; string connectionGroup = null;
Stream clientStream = null; Stream clientStream = null;
CustomBinaryReader clientStreamReader = null; CustomBinaryReader clientStreamReader = null;
StreamWriter connectStreamWriter = null; StreamWriter connectStreamWriter = null;
string tunnelHostName = null; string tunnelHostName = null;
int tunnelPort = 0; int tunnelPort = 0;
try try
{ {
connectionGroup = Dns.GetHostEntry(((IPEndPoint)Client.Client.RemoteEndPoint).Address).HostName; connectionGroup = Dns.GetHostEntry(((IPEndPoint)Client.Client.RemoteEndPoint).Address).HostName;
clientStream = Client.GetStream(); clientStream = Client.GetStream();
clientStreamReader = new CustomBinaryReader(clientStream, Encoding.ASCII); clientStreamReader = new CustomBinaryReader(clientStream, Encoding.ASCII);
string securehost = null; string securehost = null;
List<string> requestLines = new List<string>(); List<string> requestLines = new List<string>();
string tmpLine; string tmpLine;
while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine())) while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine()))
{ {
requestLines.Add(tmpLine); requestLines.Add(tmpLine);
} }
//read the first line HTTP command //read the first line HTTP command
String httpCmd = requestLines.Count > 0 ? requestLines[0] : null; String httpCmd = requestLines.Count > 0 ? requestLines[0] : null;
if (String.IsNullOrEmpty(httpCmd)) if (String.IsNullOrEmpty(httpCmd))
{ {
throw new EndOfStreamException(); throw new EndOfStreamException();
} }
//break up the line into three components //break up the line into three components
String[] splitBuffer = httpCmd.Split(spaceSplit, 3); String[] splitBuffer = httpCmd.Split(spaceSplit, 3);
String method = splitBuffer[0]; String method = splitBuffer[0];
String remoteUri = splitBuffer[1]; String remoteUri = splitBuffer[1];
Version version; Version version;
string RequestVersion; string RequestVersion;
if (splitBuffer[2] == "HTTP/1.1") if (splitBuffer[2] == "HTTP/1.1")
{ {
version = new Version(1, 1); version = new Version(1, 1);
RequestVersion = "HTTP/1.1"; RequestVersion = "HTTP/1.1";
} }
else else
{ {
version = new Version(1, 0); version = new Version(1, 0);
RequestVersion = "HTTP/1.0"; RequestVersion = "HTTP/1.0";
} }
if (splitBuffer[0].ToUpper() == "CONNECT") if (splitBuffer[0].ToUpper() == "CONNECT")
{ {
//Browser wants to create a secure tunnel //Browser wants to create a secure tunnel
//instead = we are going to perform a man in the middle "attack" //instead = we are going to perform a man in the middle "attack"
//the user's browser should warn them of the certification errors, //the user's browser should warn them of the certification errors,
//so we need to install our root certficate in users machine as Certificate Authority. //so we need to install our root certficate in users machine as Certificate Authority.
remoteUri = "https://" + splitBuffer[1]; remoteUri = "https://" + splitBuffer[1];
tunnelHostName = splitBuffer[1].Split(':')[0]; tunnelHostName = splitBuffer[1].Split(':')[0];
int.TryParse(splitBuffer[1].Split(':')[1], out tunnelPort); int.TryParse(splitBuffer[1].Split(':')[1], out tunnelPort);
if (tunnelPort == 0) tunnelPort = 80; if (tunnelPort == 0) tunnelPort = 80;
var isSecure = true; var isSecure = true;
for (int i = 1; i < requestLines.Count; i++) for (int i = 1; i < requestLines.Count; i++)
{ {
var rawHeader = requestLines[i]; var rawHeader = requestLines[i];
String[] header = rawHeader.ToLower().Trim().Split(colonSpaceSplit, 2, StringSplitOptions.None); String[] header = rawHeader.ToLower().Trim().Split(colonSpaceSplit, 2, StringSplitOptions.None);
if ((header[0] == "host")) if ((header[0] == "host"))
{ {
var hostDetails = header[1].ToLower().Trim().Split(':'); var hostDetails = header[1].ToLower().Trim().Split(':');
if (hostDetails.Length > 1) if (hostDetails.Length > 1)
{ {
isSecure = false; isSecure = false;
} }
} }
} }
requestLines.Clear(); requestLines.Clear();
connectStreamWriter = new StreamWriter(clientStream); connectStreamWriter = new StreamWriter(clientStream);
connectStreamWriter.WriteLine(RequestVersion + " 200 Connection established"); connectStreamWriter.WriteLine(RequestVersion + " 200 Connection established");
connectStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString())); connectStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString()));
connectStreamWriter.WriteLine(String.Format("connection:close")); connectStreamWriter.WriteLine(String.Format("connection:close"));
connectStreamWriter.WriteLine(); connectStreamWriter.WriteLine();
connectStreamWriter.Flush(); connectStreamWriter.Flush();
if (tunnelPort != 443) if (tunnelPort != 443)
{ {
TcpHelper.SendRaw(tunnelHostName, tunnelPort, clientStreamReader.BaseStream); TcpHelper.SendRaw(tunnelHostName, tunnelPort, clientStreamReader.BaseStream);
if (clientStream != null) if (clientStream != null)
clientStream.Close(); clientStream.Close();
return; return;
} }
Monitor.Enter(certificateAccessLock); Monitor.Enter(certificateAccessLock);
var _certificate = ProxyServer.CertManager.CreateCertificate(tunnelHostName); //CertificateHelper.GetCertificate(RootCertificateName, tunnelHostName); var _certificate = ProxyServer.CertManager.CreateCertificate(tunnelHostName); //CertificateHelper.GetCertificate(RootCertificateName, tunnelHostName);
Monitor.Exit(certificateAccessLock); Monitor.Exit(certificateAccessLock);
SslStream sslStream = null; SslStream sslStream = null;
if (!pinnedCertificateClients.Contains(tunnelHostName) && isSecure) if (!pinnedCertificateClients.Contains(tunnelHostName) && isSecure)
{ {
sslStream = new SslStream(clientStream, true); sslStream = new SslStream(clientStream, true);
try try
{ {
sslStream.AuthenticateAsServer(_certificate, false, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, false); sslStream.AuthenticateAsServer(_certificate, false, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, false);
} }
catch (AuthenticationException ex) catch (AuthenticationException ex)
{ {
if (pinnedCertificateClients.Contains(tunnelHostName) == false) if (pinnedCertificateClients.Contains(tunnelHostName) == false)
{ {
pinnedCertificateClients.Add(tunnelHostName); pinnedCertificateClients.Add(tunnelHostName);
} }
throw ex; throw ex;
} }
} }
else else
{ {
TcpHelper.SendRaw(tunnelHostName, tunnelPort, clientStreamReader.BaseStream); TcpHelper.SendRaw(tunnelHostName, tunnelPort, clientStreamReader.BaseStream);
if (clientStream != null) if (clientStream != null)
clientStream.Close(); clientStream.Close();
return; return;
} }
clientStreamReader = new CustomBinaryReader(sslStream, Encoding.ASCII); clientStreamReader = new CustomBinaryReader(sslStream, Encoding.ASCII);
//HTTPS server created - we can now decrypt the client's traffic //HTTPS server created - we can now decrypt the client's traffic
clientStream = sslStream; clientStream = sslStream;
while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine())) while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine()))
{ {
requestLines.Add(tmpLine); requestLines.Add(tmpLine);
} }
//read the new http command. //read the new http command.
httpCmd = requestLines.Count > 0 ? requestLines[0] : null; httpCmd = requestLines.Count > 0 ? requestLines[0] : null;
if (String.IsNullOrEmpty(httpCmd)) if (String.IsNullOrEmpty(httpCmd))
{ {
throw new EndOfStreamException(); throw new EndOfStreamException();
} }
securehost = remoteUri; securehost = remoteUri;
} }
int count = 0; int count = 0;
SessionEventArgs args = new SessionEventArgs(BUFFER_SIZE); SessionEventArgs args = new SessionEventArgs(BUFFER_SIZE);
while (!String.IsNullOrEmpty(httpCmd)) while (!String.IsNullOrEmpty(httpCmd))
{ {
count++; count++;
MemoryStream mw = null; MemoryStream mw = null;
StreamWriter sw = null; StreamWriter sw = null;
args = new SessionEventArgs(BUFFER_SIZE); args = new SessionEventArgs(BUFFER_SIZE);
try try
{ {
splitBuffer = httpCmd.Split(spaceSplit, 3); splitBuffer = httpCmd.Split(spaceSplit, 3);
if (splitBuffer.Length != 3) if (splitBuffer.Length != 3)
{ {
TcpHelper.SendRaw(httpCmd, tunnelHostName, ref requestLines, args.IsSecure, clientStreamReader.BaseStream); TcpHelper.SendRaw(httpCmd, tunnelHostName, ref requestLines, args.IsSSLRequest, clientStreamReader.BaseStream);
if (clientStream != null) if (clientStream != null)
clientStream.Close(); clientStream.Close();
return; return;
} }
method = splitBuffer[0]; method = splitBuffer[0];
remoteUri = splitBuffer[1]; remoteUri = splitBuffer[1];
if (splitBuffer[2] == "HTTP/1.1") if (splitBuffer[2] == "HTTP/1.1")
{ {
version = new Version(1, 1); version = new Version(1, 1);
} }
else else
{ {
version = new Version(1, 0); version = new Version(1, 0);
} }
if (securehost != null) if (securehost != null)
{ {
remoteUri = securehost + remoteUri; remoteUri = securehost + remoteUri;
args.IsSecure = true; args.IsSSLRequest = true;
} }
//construct the web request that we are going to issue on behalf of the client. //construct the web request that we are going to issue on behalf of the client.
args.ProxyRequest = (HttpWebRequest)HttpWebRequest.Create(remoteUri.Trim()); args.ProxyRequest = (HttpWebRequest)HttpWebRequest.Create(remoteUri.Trim());
args.ProxyRequest.Proxy = null; args.ProxyRequest.Proxy = null;
args.ProxyRequest.UseDefaultCredentials = true; args.ProxyRequest.UseDefaultCredentials = true;
args.ProxyRequest.Method = method; args.ProxyRequest.Method = method;
args.ProxyRequest.ProtocolVersion = version; args.ProxyRequest.ProtocolVersion = version;
args.ClientStream = clientStream; args.ClientStream = clientStream;
args.ClientStreamReader = clientStreamReader; args.ClientStreamReader = clientStreamReader;
for (int i = 1; i < requestLines.Count; i++) for (int i = 1; i < requestLines.Count; i++)
{ {
var rawHeader = requestLines[i]; var rawHeader = requestLines[i];
String[] header = rawHeader.ToLower().Trim().Split(colonSpaceSplit, 2, StringSplitOptions.None); String[] header = rawHeader.ToLower().Trim().Split(colonSpaceSplit, 2, StringSplitOptions.None);
if ((header[0] == "upgrade") && (header[1] == "websocket")) if ((header[0] == "upgrade") && (header[1] == "websocket"))
{ {
TcpHelper.SendRaw(httpCmd, tunnelHostName, ref requestLines, args.IsSecure, clientStreamReader.BaseStream); TcpHelper.SendRaw(httpCmd, tunnelHostName, ref requestLines, args.IsSSLRequest, clientStreamReader.BaseStream);
if (clientStream != null) if (clientStream != null)
clientStream.Close(); clientStream.Close();
return; return;
} }
} }
ReadRequestHeaders(ref requestLines, args.ProxyRequest); ReadRequestHeaders(ref requestLines, args.ProxyRequest);
int contentLen = (int)args.ProxyRequest.ContentLength; int contentLen = (int)args.ProxyRequest.ContentLength;
args.ProxyRequest.AllowAutoRedirect = false; args.ProxyRequest.AllowAutoRedirect = false;
args.ProxyRequest.AutomaticDecompression = DecompressionMethods.None; args.ProxyRequest.AutomaticDecompression = DecompressionMethods.None;
if (BeforeRequest != null) if (BeforeRequest != null)
{ {
args.Hostname = args.ProxyRequest.RequestUri.Host; args.RequestHostname = args.ProxyRequest.RequestUri.Host;
args.RequestURL = args.ProxyRequest.RequestUri.OriginalString; args.RequestURL = args.ProxyRequest.RequestUri.OriginalString;
args.RequestLength = contentLen; args.RequestLength = contentLen;
args.HttpVersion = version; args.RequestHttpVersion = version;
args.Port = ((IPEndPoint)Client.Client.RemoteEndPoint).Port; args.ClientPort = ((IPEndPoint)Client.Client.RemoteEndPoint).Port;
args.ipAddress = ((IPEndPoint)Client.Client.RemoteEndPoint).Address; args.ClientIpAddress = ((IPEndPoint)Client.Client.RemoteEndPoint).Address;
args.IsAlive = args.ProxyRequest.KeepAlive; args.RequestIsAlive = args.ProxyRequest.KeepAlive;
BeforeRequest(null, args); BeforeRequest(null, args);
} }
if (args.Cancel) if (args.CancelRequest)
{ {
if (args.IsAlive) if (args.RequestIsAlive)
{ {
requestLines.Clear(); requestLines.Clear();
while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine())) while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine()))
{ {
requestLines.Add(tmpLine); requestLines.Add(tmpLine);
} }
httpCmd = requestLines.Count > 0 ? requestLines[0] : null; httpCmd = requestLines.Count > 0 ? requestLines[0] : null;
continue; continue;
} }
else else
break; break;
} }
args.ProxyRequest.ConnectionGroupName = connectionGroup; args.ProxyRequest.ConnectionGroupName = connectionGroup;
args.ProxyRequest.AllowWriteStreamBuffering = true; args.ProxyRequest.AllowWriteStreamBuffering = true;
args.FinishedRequestEvent = new ManualResetEvent(false); args.FinishedRequestEvent = new ManualResetEvent(false);
if (method.ToUpper() == "POST" || method.ToUpper() == "PUT") if (method.ToUpper() == "POST" || method.ToUpper() == "PUT")
{ {
args.ProxyRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), args); args.ProxyRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), args);
} }
else else
{ {
args.ProxyRequest.BeginGetResponse(new AsyncCallback(HandleServerResponse), args); args.ProxyRequest.BeginGetResponse(new AsyncCallback(HandleServerResponse), args);
} }
if (args.IsSecure) if (args.IsSSLRequest)
{ {
if (args.ProxyRequest.Method == "POST" || args.ProxyRequest.Method == "PUT") if (args.ProxyRequest.Method == "POST" || args.ProxyRequest.Method == "PUT")
args.FinishedRequestEvent.WaitOne(); args.FinishedRequestEvent.WaitOne();
else else
args.FinishedRequestEvent.Set(); args.FinishedRequestEvent.Set();
} }
else else
args.FinishedRequestEvent.WaitOne(); args.FinishedRequestEvent.WaitOne();
httpCmd = null; httpCmd = null;
if (args.ProxyRequest.KeepAlive) if (args.ProxyRequest.KeepAlive)
{ {
requestLines.Clear(); requestLines.Clear();
while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine())) while (!String.IsNullOrEmpty(tmpLine = clientStreamReader.ReadLine()))
{ {
requestLines.Add(tmpLine); requestLines.Add(tmpLine);
} }
httpCmd = requestLines.Count() > 0 ? requestLines[0] : null; httpCmd = requestLines.Count() > 0 ? requestLines[0] : null;
} }
if (args.ServerResponse != null) if (args.ServerResponse != null)
args.ServerResponse.Close(); args.ServerResponse.Close();
} }
catch (IOException ex) catch (IOException ex)
{ {
throw ex; throw ex;
} }
catch (UriFormatException ex) catch (UriFormatException ex)
{ {
throw ex; throw ex;
} }
catch (WebException ex) catch (WebException ex)
{ {
throw ex; throw ex;
} }
finally finally
{ {
if (sw != null) sw.Close(); if (sw != null) sw.Close();
if (mw != null) mw.Close(); if (mw != null) mw.Close();
if (args.ProxyRequest != null) args.ProxyRequest.Abort(); if (args.ProxyRequest != null) args.ProxyRequest.Abort();
if (args.ServerResponseStream != null) args.ServerResponseStream.Close(); if (args.ServerResponseStream != null) args.ServerResponseStream.Close();
} }
} }
} }
catch (AuthenticationException ex) catch (AuthenticationException ex)
{ {
Debug.WriteLine(ex.Message); Debug.WriteLine(ex.Message);
} }
catch (EndOfStreamException ex) catch (EndOfStreamException ex)
{ {
Debug.WriteLine(ex.Message); Debug.WriteLine(ex.Message);
} }
catch (IOException ex) catch (IOException ex)
{ {
Debug.WriteLine(ex.Message); Debug.WriteLine(ex.Message);
} }
catch (UriFormatException ex) catch (UriFormatException ex)
{ {
Debug.WriteLine(ex.Message); Debug.WriteLine(ex.Message);
} }
catch (WebException ex) catch (WebException ex)
{ {
Debug.WriteLine(ex.Message); Debug.WriteLine(ex.Message);
} }
finally finally
{ {
if (connectStreamWriter != null) if (connectStreamWriter != null)
connectStreamWriter.Close(); connectStreamWriter.Close();
if (clientStreamReader != null) if (clientStreamReader != null)
clientStreamReader.Close(); clientStreamReader.Close();
if (clientStream != null) if (clientStream != null)
clientStream.Close(); clientStream.Close();
} }
} }
private static void ReadRequestHeaders(ref List<string> RequestLines, HttpWebRequest WebRequest) private static void ReadRequestHeaders(ref List<string> RequestLines, HttpWebRequest WebRequest)
{ {
for (int i = 1; i < RequestLines.Count; i++) for (int i = 1; i < RequestLines.Count; i++)
{ {
String httpCmd = RequestLines[i]; String httpCmd = RequestLines[i];
String[] header = httpCmd.Split(colonSpaceSplit, 2, StringSplitOptions.None); String[] header = httpCmd.Split(colonSpaceSplit, 2, StringSplitOptions.None);
if (!String.IsNullOrEmpty(header[0].Trim())) if (!String.IsNullOrEmpty(header[0].Trim()))
switch (header[0].ToLower()) switch (header[0].ToLower())
{ {
case "accept": case "accept":
WebRequest.Accept = header[1]; WebRequest.Accept = header[1];
break; break;
case "accept-encoding": case "accept-encoding":
WebRequest.Headers.Add(header[0], "gzip,deflate,zlib"); WebRequest.Headers.Add(header[0], "gzip,deflate,zlib");
break; break;
case "cookie": case "cookie":
WebRequest.Headers["Cookie"] = header[1]; WebRequest.Headers["Cookie"] = header[1];
break; break;
case "connection": case "connection":
if (header[1].ToLower() == "keep-alive") if (header[1].ToLower() == "keep-alive")
WebRequest.KeepAlive = true; WebRequest.KeepAlive = true;
break; break;
case "content-length": case "content-length":
int contentLen; int contentLen;
int.TryParse(header[1], out contentLen); int.TryParse(header[1], out contentLen);
if (contentLen != 0) if (contentLen != 0)
WebRequest.ContentLength = contentLen; WebRequest.ContentLength = contentLen;
break; break;
case "content-type": case "content-type":
WebRequest.ContentType = header[1]; WebRequest.ContentType = header[1];
break; break;
case "expect": case "expect":
if (header[1].ToLower() == "100-continue") if (header[1].ToLower() == "100-continue")
WebRequest.ServicePoint.Expect100Continue = true; WebRequest.ServicePoint.Expect100Continue = true;
else else
WebRequest.Expect = header[1]; WebRequest.Expect = header[1];
break; break;
case "host": case "host":
WebRequest.Host = header[1]; WebRequest.Host = header[1];
break; break;
case "if-modified-since": case "if-modified-since":
String[] sb = header[1].Trim().Split(semiSplit); String[] sb = header[1].Trim().Split(semiSplit);
DateTime d; DateTime d;
if (DateTime.TryParse(sb[0], out d)) if (DateTime.TryParse(sb[0], out d))
WebRequest.IfModifiedSince = d; WebRequest.IfModifiedSince = d;
break; break;
case "proxy-connection": case "proxy-connection":
break; break;
case "range": case "range":
var startEnd = header[1].Replace(Environment.NewLine, "").Remove(0, 6).Split('-'); var startEnd = header[1].Replace(Environment.NewLine, "").Remove(0, 6).Split('-');
if (startEnd.Length > 1) { if (!String.IsNullOrEmpty(startEnd[1])) WebRequest.AddRange(int.Parse(startEnd[0]), int.Parse(startEnd[1])); else WebRequest.AddRange(int.Parse(startEnd[0])); } if (startEnd.Length > 1) { if (!String.IsNullOrEmpty(startEnd[1])) WebRequest.AddRange(int.Parse(startEnd[0]), int.Parse(startEnd[1])); else WebRequest.AddRange(int.Parse(startEnd[0])); }
else else
WebRequest.AddRange(int.Parse(startEnd[0])); WebRequest.AddRange(int.Parse(startEnd[0]));
break; break;
case "referer": case "referer":
WebRequest.Referer = header[1]; WebRequest.Referer = header[1];
break; break;
case "user-agent": case "user-agent":
WebRequest.UserAgent = header[1]; WebRequest.UserAgent = header[1];
break; break;
case "transfer-encoding": case "transfer-encoding":
if (header[1].ToLower() == "chunked") if (header[1].ToLower() == "chunked")
WebRequest.SendChunked = true; WebRequest.SendChunked = true;
else else
WebRequest.SendChunked = false; WebRequest.SendChunked = false;
break; break;
case "upgrade": case "upgrade":
if (header[1].ToLower() == "http/1.1") if (header[1].ToLower() == "http/1.1")
WebRequest.Headers.Add(header[0], header[1]); WebRequest.Headers.Add(header[0], header[1]);
break; break;
default: default:
if (header.Length > 0) if (header.Length > 0)
WebRequest.Headers.Add(header[0], header[1]); WebRequest.Headers.Add(header[0], header[1]);
else else
WebRequest.Headers.Add(header[0], ""); WebRequest.Headers.Add(header[0], "");
break; break;
} }
} }
} }
private static void GetRequestStreamCallback(IAsyncResult AsynchronousResult) private static void GetRequestStreamCallback(IAsyncResult AsynchronousResult)
{ {
var args = (SessionEventArgs)AsynchronousResult.AsyncState; var args = (SessionEventArgs)AsynchronousResult.AsyncState;
// End the operation // End the operation
Stream postStream = args.ProxyRequest.EndGetRequestStream(AsynchronousResult); Stream postStream = args.ProxyRequest.EndGetRequestStream(AsynchronousResult);
if (args.ProxyRequest.ContentLength > 0) if (args.ProxyRequest.ContentLength > 0)
{ {
args.ProxyRequest.AllowWriteStreamBuffering = true; args.ProxyRequest.AllowWriteStreamBuffering = true;
try try
{ {
int totalbytesRead = 0; int totalbytesRead = 0;
int bytesToRead; int bytesToRead;
if (args.ProxyRequest.ContentLength < BUFFER_SIZE) if (args.ProxyRequest.ContentLength < BUFFER_SIZE)
{ {
bytesToRead = (int)args.ProxyRequest.ContentLength; bytesToRead = (int)args.ProxyRequest.ContentLength;
} }
else else
bytesToRead = BUFFER_SIZE; bytesToRead = BUFFER_SIZE;
while (totalbytesRead < (int)args.ProxyRequest.ContentLength) while (totalbytesRead < (int)args.ProxyRequest.ContentLength)
{ {
var buffer = args.ClientStreamReader.ReadBytes(bytesToRead); var buffer = args.ClientStreamReader.ReadBytes(bytesToRead);
totalbytesRead += buffer.Length; totalbytesRead += buffer.Length;
int RemainingBytes = (int)args.ProxyRequest.ContentLength - totalbytesRead; int RemainingBytes = (int)args.ProxyRequest.ContentLength - totalbytesRead;
if (RemainingBytes < bytesToRead) if (RemainingBytes < bytesToRead)
{ {
bytesToRead = RemainingBytes; bytesToRead = RemainingBytes;
} }
postStream.Write(buffer, 0, buffer.Length); postStream.Write(buffer, 0, buffer.Length);
} }
postStream.Close(); postStream.Close();
} }
catch (IOException ex) catch (IOException ex)
{ {
args.ProxyRequest.KeepAlive = false; args.ProxyRequest.KeepAlive = false;
args.FinishedRequestEvent.Set(); args.FinishedRequestEvent.Set();
Debug.WriteLine(ex.Message); Debug.WriteLine(ex.Message);
return; return;
} }
catch (WebException ex) catch (WebException ex)
{ {
args.ProxyRequest.KeepAlive = false; args.ProxyRequest.KeepAlive = false;
args.FinishedRequestEvent.Set(); args.FinishedRequestEvent.Set();
Debug.WriteLine(ex.Message); Debug.WriteLine(ex.Message);
return; return;
} }
} }
else if (args.ProxyRequest.SendChunked) else if (args.ProxyRequest.SendChunked)
{ {
args.ProxyRequest.AllowWriteStreamBuffering = true; args.ProxyRequest.AllowWriteStreamBuffering = true;
try try
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
byte[] byteRead = new byte[1]; byte[] byteRead = new byte[1];
while (true) while (true)
{ {
args.ClientStream.Read(byteRead, 0, 1); args.ClientStream.Read(byteRead, 0, 1);
sb.Append(Encoding.ASCII.GetString(byteRead)); sb.Append(Encoding.ASCII.GetString(byteRead));
if (sb.ToString().EndsWith(Environment.NewLine)) if (sb.ToString().EndsWith(Environment.NewLine))
{ {
var chunkSizeInHex = sb.ToString().Replace(Environment.NewLine, String.Empty); var chunkSizeInHex = sb.ToString().Replace(Environment.NewLine, String.Empty);
var chunckSize = int.Parse(chunkSizeInHex, System.Globalization.NumberStyles.HexNumber); var chunckSize = int.Parse(chunkSizeInHex, System.Globalization.NumberStyles.HexNumber);
if (chunckSize == 0) if (chunckSize == 0)
{ {
for (int i = 0; i < Encoding.ASCII.GetByteCount(Environment.NewLine); i++) for (int i = 0; i < Encoding.ASCII.GetByteCount(Environment.NewLine); i++)
{ {
args.ClientStream.ReadByte(); args.ClientStream.ReadByte();
} }
break; break;
} }
var totalbytesRead = 0; var totalbytesRead = 0;
int bytesToRead; int bytesToRead;
if (chunckSize < BUFFER_SIZE) if (chunckSize < BUFFER_SIZE)
{ {
bytesToRead = chunckSize; bytesToRead = chunckSize;
} }
else else
bytesToRead = BUFFER_SIZE; bytesToRead = BUFFER_SIZE;
while (totalbytesRead < chunckSize) while (totalbytesRead < chunckSize)
{ {
var buffer = args.ClientStreamReader.ReadBytes(bytesToRead); var buffer = args.ClientStreamReader.ReadBytes(bytesToRead);
totalbytesRead += buffer.Length; totalbytesRead += buffer.Length;
int RemainingBytes = chunckSize - totalbytesRead; int RemainingBytes = chunckSize - totalbytesRead;
if (RemainingBytes < bytesToRead) if (RemainingBytes < bytesToRead)
{ {
bytesToRead = RemainingBytes; bytesToRead = RemainingBytes;
} }
postStream.Write(buffer, 0, buffer.Length); postStream.Write(buffer, 0, buffer.Length);
} }
for (int i = 0; i < Encoding.ASCII.GetByteCount(Environment.NewLine); i++) for (int i = 0; i < Encoding.ASCII.GetByteCount(Environment.NewLine); i++)
{ {
args.ClientStream.ReadByte(); args.ClientStream.ReadByte();
} }
sb.Clear(); sb.Clear();
} }
} }
postStream.Close(); postStream.Close();
} }
catch (IOException ex) catch (IOException ex)
{ {
if (postStream != null) if (postStream != null)
postStream.Close(); postStream.Close();
args.ProxyRequest.KeepAlive = false; args.ProxyRequest.KeepAlive = false;
args.FinishedRequestEvent.Set(); args.FinishedRequestEvent.Set();
Debug.WriteLine(ex.Message); Debug.WriteLine(ex.Message);
return; return;
} }
catch (WebException ex) catch (WebException ex)
{ {
if (postStream != null) if (postStream != null)
postStream.Close(); postStream.Close();
args.ProxyRequest.KeepAlive = false; args.ProxyRequest.KeepAlive = false;
args.FinishedRequestEvent.Set(); args.FinishedRequestEvent.Set();
Debug.WriteLine(ex.Message); Debug.WriteLine(ex.Message);
return; return;
} }
} }
args.ProxyRequest.BeginGetResponse(new AsyncCallback(HandleServerResponse), args); args.ProxyRequest.BeginGetResponse(new AsyncCallback(HandleServerResponse), args);
} }
} }
} }
\ No newline at end of file
...@@ -62,25 +62,25 @@ namespace Titanium.Web.Proxy ...@@ -62,25 +62,25 @@ namespace Titanium.Web.Proxy
switch (args.ServerResponse.ContentEncoding) switch (args.ServerResponse.ContentEncoding)
{ {
case "gzip": case "gzip":
data = CompressionHelper.CompressGzip(args.ResponseString, args.Encoding); data = CompressionHelper.CompressGzip(args.ResponseHtmlBody, args.Encoding);
WriteResponseStatus(args.ServerResponse.ProtocolVersion, args.ServerResponse.StatusCode, args.ServerResponse.StatusDescription, responseWriter); WriteResponseStatus(args.ServerResponse.ProtocolVersion, args.ServerResponse.StatusCode, args.ServerResponse.StatusDescription, responseWriter);
WriteResponseHeaders(responseWriter, responseHeaders, data.Length); WriteResponseHeaders(responseWriter, responseHeaders, data.Length);
SendData(clientWriteStream, data, isChunked); SendData(clientWriteStream, data, isChunked);
break; break;
case "deflate": case "deflate":
data = CompressionHelper.CompressDeflate(args.ResponseString, args.Encoding); data = CompressionHelper.CompressDeflate(args.ResponseHtmlBody, args.Encoding);
WriteResponseStatus(args.ServerResponse.ProtocolVersion, args.ServerResponse.StatusCode, args.ServerResponse.StatusDescription, responseWriter); WriteResponseStatus(args.ServerResponse.ProtocolVersion, args.ServerResponse.StatusCode, args.ServerResponse.StatusDescription, responseWriter);
WriteResponseHeaders(responseWriter, responseHeaders, data.Length); WriteResponseHeaders(responseWriter, responseHeaders, data.Length);
SendData(clientWriteStream, data, isChunked); SendData(clientWriteStream, data, isChunked);
break; break;
case "zlib": case "zlib":
data = CompressionHelper.CompressZlib(args.ResponseString, args.Encoding); data = CompressionHelper.CompressZlib(args.ResponseHtmlBody, args.Encoding);
WriteResponseStatus(args.ServerResponse.ProtocolVersion, args.ServerResponse.StatusCode, args.ServerResponse.StatusDescription, responseWriter); WriteResponseStatus(args.ServerResponse.ProtocolVersion, args.ServerResponse.StatusCode, args.ServerResponse.StatusDescription, responseWriter);
WriteResponseHeaders(responseWriter, responseHeaders, data.Length); WriteResponseHeaders(responseWriter, responseHeaders, data.Length);
SendData(clientWriteStream, data, isChunked); SendData(clientWriteStream, data, isChunked);
break; break;
default: default:
data = EncodeData(args.ResponseString, args.Encoding); data = EncodeData(args.ResponseHtmlBody, args.Encoding);
WriteResponseStatus(args.ServerResponse.ProtocolVersion, args.ServerResponse.StatusCode, args.ServerResponse.StatusDescription, responseWriter); WriteResponseStatus(args.ServerResponse.ProtocolVersion, args.ServerResponse.StatusCode, args.ServerResponse.StatusDescription, responseWriter);
WriteResponseHeaders(responseWriter, responseHeaders, data.Length); WriteResponseHeaders(responseWriter, responseHeaders, data.Length);
SendData(clientWriteStream, data, isChunked); SendData(clientWriteStream, data, isChunked);
......
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