Commit cb8fd1ad authored by Honfika's avatar Honfika

Tunnel Connect events renamed, call the BeforeResponse event handlers before...

Tunnel Connect events renamed, call the BeforeResponse event handlers before sending the authentication failed response
parent e6069349
...@@ -69,8 +69,8 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -69,8 +69,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
}; };
//Fired when a CONNECT request is received //Fired when a CONNECT request is received
explicitEndPoint.TunnelConnectRequest += OnTunnelConnectRequest; explicitEndPoint.BeforeTunnelConnectRequest += OnBeforeTunnelConnectRequest;
explicitEndPoint.TunnelConnectResponse += OnTunnelConnectResponse; explicitEndPoint.BeforeTunnelConnectResponse += OnBeforeTunnelConnectResponse;
//An explicit endpoint is where the client knows about the existence of a proxy //An explicit endpoint is where the client knows about the existence of a proxy
//So client sends request in a proxy friendly manner //So client sends request in a proxy friendly manner
...@@ -108,8 +108,8 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -108,8 +108,8 @@ namespace Titanium.Web.Proxy.Examples.Basic
public void Stop() public void Stop()
{ {
explicitEndPoint.TunnelConnectRequest -= OnTunnelConnectRequest; explicitEndPoint.BeforeTunnelConnectRequest -= OnBeforeTunnelConnectRequest;
explicitEndPoint.TunnelConnectResponse -= OnTunnelConnectResponse; explicitEndPoint.BeforeTunnelConnectResponse -= OnBeforeTunnelConnectResponse;
proxyServer.BeforeRequest -= OnRequest; proxyServer.BeforeRequest -= OnRequest;
proxyServer.BeforeResponse -= OnResponse; proxyServer.BeforeResponse -= OnResponse;
...@@ -122,7 +122,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -122,7 +122,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
//proxyServer.CertificateManager.RemoveTrustedRootCertificates(); //proxyServer.CertificateManager.RemoveTrustedRootCertificates();
} }
private async Task OnTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{ {
string hostname = e.WebSession.Request.RequestUri.Host; string hostname = e.WebSession.Request.RequestUri.Host;
Console.WriteLine("Tunnel to: " + hostname); Console.WriteLine("Tunnel to: " + hostname);
...@@ -136,7 +136,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -136,7 +136,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
} }
} }
private async Task OnTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e) private async Task OnBeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e)
{ {
} }
......
...@@ -102,8 +102,8 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -102,8 +102,8 @@ namespace Titanium.Web.Proxy.Examples.Wpf
proxyServer.BeforeRequest += ProxyServer_BeforeRequest; proxyServer.BeforeRequest += ProxyServer_BeforeRequest;
proxyServer.BeforeResponse += ProxyServer_BeforeResponse; proxyServer.BeforeResponse += ProxyServer_BeforeResponse;
explicitEndPoint.TunnelConnectRequest += ProxyServer_TunnelConnectRequest; explicitEndPoint.BeforeTunnelConnectRequest += ProxyServer_BeforeTunnelConnectRequest;
explicitEndPoint.TunnelConnectResponse += ProxyServer_TunnelConnectResponse; explicitEndPoint.BeforeTunnelConnectResponse += ProxyServer_BeforeTunnelConnectResponse;
proxyServer.ClientConnectionCountChanged += delegate { Dispatcher.Invoke(() => { ClientConnectionCount = proxyServer.ClientConnectionCount; }); }; proxyServer.ClientConnectionCountChanged += delegate { Dispatcher.Invoke(() => { ClientConnectionCount = proxyServer.ClientConnectionCount; }); };
proxyServer.ServerConnectionCountChanged += delegate { Dispatcher.Invoke(() => { ServerConnectionCount = proxyServer.ServerConnectionCount; }); }; proxyServer.ServerConnectionCountChanged += delegate { Dispatcher.Invoke(() => { ServerConnectionCount = proxyServer.ServerConnectionCount; }); };
proxyServer.Start(); proxyServer.Start();
...@@ -113,7 +113,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -113,7 +113,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
InitializeComponent(); InitializeComponent();
} }
private async Task ProxyServer_TunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) private async Task ProxyServer_BeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{ {
await Dispatcher.InvokeAsync(() => await Dispatcher.InvokeAsync(() =>
{ {
...@@ -121,7 +121,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -121,7 +121,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
}); });
} }
private async Task ProxyServer_TunnelConnectResponse(object sender, SessionEventArgs e) private async Task ProxyServer_BeforeTunnelConnectResponse(object sender, SessionEventArgs e)
{ {
await Dispatcher.InvokeAsync(() => await Dispatcher.InvokeAsync(() =>
{ {
......
...@@ -27,13 +27,13 @@ namespace Titanium.Web.Proxy.Models ...@@ -27,13 +27,13 @@ namespace Titanium.Web.Proxy.Models
/// Valid only for explicit endpoints /// Valid only for explicit endpoints
/// Set the <see cref="TunnelConnectSessionEventArgs.Excluded"/> property to true if this HTTP connect request should'nt be decrypted and instead be relayed /// Set the <see cref="TunnelConnectSessionEventArgs.Excluded"/> property to true if this HTTP connect request should'nt be decrypted and instead be relayed
/// </summary> /// </summary>
public event AsyncEventHandler<TunnelConnectSessionEventArgs> TunnelConnectRequest; public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectRequest;
/// <summary> /// <summary>
/// Intercept tunnel connect response /// Intercept tunnel connect response
/// Valid only for explicit endpoints /// Valid only for explicit endpoints
/// </summary> /// </summary>
public event AsyncEventHandler<TunnelConnectSessionEventArgs> TunnelConnectResponse; public event AsyncEventHandler<TunnelConnectSessionEventArgs> BeforeTunnelConnectResponse;
/// <summary> /// <summary>
/// Constructor. /// Constructor.
...@@ -45,20 +45,20 @@ namespace Titanium.Web.Proxy.Models ...@@ -45,20 +45,20 @@ namespace Titanium.Web.Proxy.Models
{ {
} }
internal async Task InvokeTunnectConnectRequest(ProxyServer proxyServer, TunnelConnectSessionEventArgs connectArgs, Action<Exception> exceptionFunc) internal async Task InvokeBeforeTunnelConnectRequest(ProxyServer proxyServer, TunnelConnectSessionEventArgs connectArgs, Action<Exception> exceptionFunc)
{ {
if (TunnelConnectRequest != null) if (BeforeTunnelConnectRequest != null)
{ {
await TunnelConnectRequest.InvokeAsync(proxyServer, connectArgs, exceptionFunc); await BeforeTunnelConnectRequest.InvokeAsync(proxyServer, connectArgs, exceptionFunc);
} }
} }
internal async Task InvokeTunnectConnectResponse(ProxyServer proxyServer, TunnelConnectSessionEventArgs connectArgs, Action<Exception> exceptionFunc, bool isClientHello = false) internal async Task InvokeBeforeTunnectConnectResponse(ProxyServer proxyServer, TunnelConnectSessionEventArgs connectArgs, Action<Exception> exceptionFunc, bool isClientHello = false)
{ {
if (TunnelConnectResponse != null) if (BeforeTunnelConnectResponse != null)
{ {
connectArgs.IsHttpsConnect = isClientHello; connectArgs.IsHttpsConnect = isClientHello;
await TunnelConnectResponse.InvokeAsync(proxyServer, connectArgs, exceptionFunc); await BeforeTunnelConnectResponse.InvokeAsync(proxyServer, connectArgs, exceptionFunc);
} }
} }
} }
......
...@@ -196,7 +196,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -196,7 +196,7 @@ namespace Titanium.Web.Proxy.Network
/// <param name="rootCertificateIssuerName">Name of root certificate issuer.</param> /// <param name="rootCertificateIssuerName">Name of root certificate issuer.</param>
/// <param name="userTrustRootCertificate"></param> /// <param name="userTrustRootCertificate"></param>
/// <param name="machineTrustRootCertificate">Note:setting machineTrustRootCertificate to true will force userTrustRootCertificate to true</param> /// <param name="machineTrustRootCertificate">Note:setting machineTrustRootCertificate to true will force userTrustRootCertificate to true</param>
/// <param name="trustRootCertificateAsAdmin "></param> /// <param name="trustRootCertificateAsAdmin"></param>
/// <param name="exceptionFunc"></param> /// <param name="exceptionFunc"></param>
internal CertificateManager(string rootCertificateName, string rootCertificateIssuerName, bool userTrustRootCertificate, bool machineTrustRootCertificate, bool trustRootCertificateAsAdmin, Action < Exception> exceptionFunc) internal CertificateManager(string rootCertificateName, string rootCertificateIssuerName, bool userTrustRootCertificate, bool machineTrustRootCertificate, bool trustRootCertificateAsAdmin, Action < Exception> exceptionFunc)
{ {
...@@ -310,6 +310,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -310,6 +310,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary> /// <summary>
/// Make current machine trust the Root Certificate used by this proxy /// Make current machine trust the Root Certificate used by this proxy
/// </summary> /// </summary>
/// <param name="storeName"></param>
/// <param name="storeLocation"></param> /// <param name="storeLocation"></param>
/// <returns></returns> /// <returns></returns>
private void InstallCertificate(StoreName storeName, StoreLocation storeLocation) private void InstallCertificate(StoreName storeName, StoreLocation storeLocation)
...@@ -348,7 +349,9 @@ namespace Titanium.Web.Proxy.Network ...@@ -348,7 +349,9 @@ namespace Titanium.Web.Proxy.Network
/// <summary> /// <summary>
/// Remove the Root Certificate trust /// Remove the Root Certificate trust
/// </summary> /// </summary>
/// <param name="storeName"></param>
/// <param name="storeLocation"></param> /// <param name="storeLocation"></param>
/// <param name="certificate"></param>
/// <returns></returns> /// <returns></returns>
private void UninstallCertificate(StoreName storeName, StoreLocation storeLocation, X509Certificate2 certificate) private void UninstallCertificate(StoreName storeName, StoreLocation storeLocation, X509Certificate2 certificate)
{ {
......
...@@ -15,7 +15,7 @@ namespace Titanium.Web.Proxy ...@@ -15,7 +15,7 @@ namespace Titanium.Web.Proxy
{ {
public partial class ProxyServer public partial class ProxyServer
{ {
private async Task<bool> CheckAuthorization(HttpResponseWriter clientStreamWriter, SessionEventArgs session) private async Task<bool> CheckAuthorization(SessionEventArgs session)
{ {
if (AuthenticateUserFunc == null) if (AuthenticateUserFunc == null)
{ {
...@@ -29,7 +29,7 @@ namespace Titanium.Web.Proxy ...@@ -29,7 +29,7 @@ namespace Titanium.Web.Proxy
var header = httpHeaders.GetFirstHeader(KnownHeaders.ProxyAuthorization); var header = httpHeaders.GetFirstHeader(KnownHeaders.ProxyAuthorization);
if (header == null) if (header == null)
{ {
session.WebSession.Response = await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Required"); session.WebSession.Response = SendAuthentication407Response("Proxy Authentication Required");
return false; return false;
} }
...@@ -37,7 +37,7 @@ namespace Titanium.Web.Proxy ...@@ -37,7 +37,7 @@ namespace Titanium.Web.Proxy
if (headerValueParts.Length != 2 || !headerValueParts[0].EqualsIgnoreCase(KnownHeaders.ProxyAuthorizationBasic)) if (headerValueParts.Length != 2 || !headerValueParts[0].EqualsIgnoreCase(KnownHeaders.ProxyAuthorizationBasic))
{ {
//Return not authorized //Return not authorized
session.WebSession.Response = await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Invalid"); session.WebSession.Response = SendAuthentication407Response("Proxy Authentication Invalid");
return false; return false;
} }
...@@ -46,25 +46,32 @@ namespace Titanium.Web.Proxy ...@@ -46,25 +46,32 @@ namespace Titanium.Web.Proxy
if (colonIndex == -1) if (colonIndex == -1)
{ {
//Return not authorized //Return not authorized
session.WebSession.Response = await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Invalid"); session.WebSession.Response = SendAuthentication407Response("Proxy Authentication Invalid");
return false; return false;
} }
string username = decoded.Substring(0, colonIndex); string username = decoded.Substring(0, colonIndex);
string password = decoded.Substring(colonIndex + 1); string password = decoded.Substring(colonIndex + 1);
return await AuthenticateUserFunc(username, password); bool authenticated = await AuthenticateUserFunc(username, password);
if (!authenticated)
{
//Return not authorized
session.WebSession.Response = SendAuthentication407Response("Proxy Authentication Invalid");
}
return authenticated;
} }
catch (Exception e) catch (Exception e)
{ {
ExceptionFunc(new ProxyAuthorizationException("Error whilst authorizing request", e, httpHeaders)); ExceptionFunc(new ProxyAuthorizationException("Error whilst authorizing request", e, httpHeaders));
//Return not authorized //Return not authorized
session.WebSession.Response = await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Invalid"); session.WebSession.Response = SendAuthentication407Response("Proxy Authentication Invalid");
return false; return false;
} }
} }
private async Task<Response> SendAuthentication407Response(HttpResponseWriter clientStreamWriter, string description) private Response SendAuthentication407Response(string description)
{ {
var response = new Response var response = new Response
{ {
...@@ -77,7 +84,6 @@ namespace Titanium.Web.Proxy ...@@ -77,7 +84,6 @@ namespace Titanium.Web.Proxy
response.Headers.AddHeader(KnownHeaders.ProxyConnection, KnownHeaders.ProxyConnectionClose); response.Headers.AddHeader(KnownHeaders.ProxyConnection, KnownHeaders.ProxyConnectionClose);
response.Headers.FixProxyHeaders(); response.Headers.FixProxyHeaders();
await clientStreamWriter.WriteResponseAsync(response);
return response; return response;
} }
} }
......
...@@ -210,7 +210,7 @@ namespace Titanium.Web.Proxy ...@@ -210,7 +210,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="userTrustRootCertificate"></param> /// <param name="userTrustRootCertificate"></param>
/// <param name="machineTrustRootCertificate">Note:setting machineTrustRootCertificate to true will force userTrustRootCertificate to true</param> /// <param name="machineTrustRootCertificate">Note:setting machineTrustRootCertificate to true will force userTrustRootCertificate to true</param>
/// <param name="trustRootCertificateAsAdmin "></param> /// <param name="trustRootCertificateAsAdmin"></param>
public ProxyServer(bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false) : this(null, null, userTrustRootCertificate, machineTrustRootCertificate, trustRootCertificateAsAdmin) public ProxyServer(bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false) : this(null, null, userTrustRootCertificate, machineTrustRootCertificate, trustRootCertificateAsAdmin)
{ {
} }
...@@ -222,7 +222,7 @@ namespace Titanium.Web.Proxy ...@@ -222,7 +222,7 @@ namespace Titanium.Web.Proxy
/// <param name="rootCertificateIssuerName">Name of root certificate issuer.</param> /// <param name="rootCertificateIssuerName">Name of root certificate issuer.</param>
/// <param name="userTrustRootCertificate"></param> /// <param name="userTrustRootCertificate"></param>
/// <param name="machineTrustRootCertificate">Note:setting machineTrustRootCertificate to true will force userTrustRootCertificate to true</param> /// <param name="machineTrustRootCertificate">Note:setting machineTrustRootCertificate to true will force userTrustRootCertificate to true</param>
/// <param name="trustRootCertificateAsAdmin "></param> /// <param name="trustRootCertificateAsAdmin"></param>
public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false) public ProxyServer(string rootCertificateName, string rootCertificateIssuerName, bool userTrustRootCertificate = true, bool machineTrustRootCertificate = false, bool trustRootCertificateAsAdmin = false)
{ {
//default values //default values
...@@ -660,6 +660,22 @@ namespace Titanium.Web.Proxy ...@@ -660,6 +660,22 @@ namespace Titanium.Web.Proxy
endPoint.Listener.Server.Dispose(); endPoint.Listener.Server.Dispose();
} }
private async Task InvokeBeforeRequest(SessionEventArgs args)
{
if (BeforeRequest != null)
{
await BeforeRequest.InvokeAsync(this, args, ExceptionFunc);
}
}
private async Task InvokeBeforeResponse(SessionEventArgs args)
{
if (BeforeResponse != null)
{
await BeforeResponse.InvokeAsync(this, args, ExceptionFunc);
}
}
internal void UpdateClientConnectionCount(bool increment) internal void UpdateClientConnectionCount(bool increment)
{ {
if (increment) if (increment)
......
...@@ -77,14 +77,17 @@ namespace Titanium.Web.Proxy ...@@ -77,14 +77,17 @@ namespace Titanium.Web.Proxy
connectArgs.ProxyClient.TcpClient = tcpClient; connectArgs.ProxyClient.TcpClient = tcpClient;
connectArgs.ProxyClient.ClientStream = clientStream; connectArgs.ProxyClient.ClientStream = clientStream;
await endPoint.InvokeTunnectConnectRequest(this, connectArgs, ExceptionFunc); await endPoint.InvokeBeforeTunnelConnectRequest(this, connectArgs, ExceptionFunc);
//filter out excluded host names //filter out excluded host names
bool excluded = connectArgs.Excluded; bool excluded = connectArgs.Excluded;
if (await CheckAuthorization(clientStreamWriter, connectArgs) == false) if (await CheckAuthorization(connectArgs) == false)
{ {
await endPoint.InvokeTunnectConnectResponse(this, connectArgs, ExceptionFunc); await endPoint.InvokeBeforeTunnectConnectResponse(this, connectArgs, ExceptionFunc);
//send the response
await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response);
return; return;
} }
...@@ -102,7 +105,7 @@ namespace Titanium.Web.Proxy ...@@ -102,7 +105,7 @@ namespace Titanium.Web.Proxy
connectRequest.ClientHelloInfo = clientHelloInfo; connectRequest.ClientHelloInfo = clientHelloInfo;
} }
await endPoint.InvokeTunnectConnectResponse(this, connectArgs, ExceptionFunc, isClientHello); await endPoint.InvokeBeforeTunnectConnectResponse(this, connectArgs, ExceptionFunc, isClientHello);
if (!excluded && isClientHello) if (!excluded && isClientHello)
{ {
...@@ -352,8 +355,12 @@ namespace Titanium.Web.Proxy ...@@ -352,8 +355,12 @@ namespace Titanium.Web.Proxy
args.ProxyClient.ClientStreamWriter = clientStreamWriter; args.ProxyClient.ClientStreamWriter = clientStreamWriter;
//proxy authorization check //proxy authorization check
if (!args.IsTransparent && httpsConnectHostname == null && await CheckAuthorization(clientStreamWriter, args) == false) if (!args.IsTransparent && httpsConnectHostname == null && await CheckAuthorization(args) == false)
{ {
await InvokeBeforeResponse(args);
//send the response
await clientStreamWriter.WriteResponseAsync(args.WebSession.Response);
break; break;
} }
...@@ -372,10 +379,7 @@ namespace Titanium.Web.Proxy ...@@ -372,10 +379,7 @@ namespace Titanium.Web.Proxy
} }
//If user requested interception do it //If user requested interception do it
if (BeforeRequest != null) await InvokeBeforeRequest(args);
{
await BeforeRequest.InvokeAsync(this, args, ExceptionFunc);
}
var response = args.WebSession.Response; var response = args.WebSession.Response;
...@@ -428,9 +432,9 @@ namespace Titanium.Web.Proxy ...@@ -428,9 +432,9 @@ namespace Titanium.Web.Proxy
} }
//If user requested call back then do it //If user requested call back then do it
if (BeforeResponse != null && !args.WebSession.Response.ResponseLocked) if (!args.WebSession.Response.ResponseLocked)
{ {
await BeforeResponse.InvokeAsync(this, args, ExceptionFunc); await InvokeBeforeResponse(args);
} }
await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize, await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize,
......
...@@ -35,10 +35,10 @@ namespace Titanium.Web.Proxy ...@@ -35,10 +35,10 @@ namespace Titanium.Web.Proxy
args.ReRequest = false; args.ReRequest = false;
//If user requested call back then do it //if user requested call back then do it
if (BeforeResponse != null && !response.ResponseLocked) if (!response.ResponseLocked)
{ {
await BeforeResponse.InvokeAsync(this, args, ExceptionFunc); await InvokeBeforeResponse(args);
} }
//if user requested to send request again //if user requested to send request again
......
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