Commit 26d815c3 authored by Honfika's avatar Honfika

BlockConnect property added to TunenelConnectSessionEventArgs

parent 1b1bda0e
...@@ -128,7 +128,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -128,7 +128,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
}); });
} }
private async Task ProxyServer_BeforeTunnelConnectResponse(object sender, SessionEventArgs e) private async Task ProxyServer_BeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e)
{ {
await Dispatcher.InvokeAsync(() => await Dispatcher.InvokeAsync(() =>
{ {
...@@ -191,7 +191,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -191,7 +191,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
}); });
} }
private SessionListItem AddSession(SessionEventArgs e) private SessionListItem AddSession(SessionEventArgsBase e)
{ {
var item = CreateSessionListItem(e); var item = CreateSessionListItem(e);
Sessions.Add(item); Sessions.Add(item);
...@@ -199,7 +199,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf ...@@ -199,7 +199,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
return item; return item;
} }
private SessionListItem CreateSessionListItem(SessionEventArgs e) private SessionListItem CreateSessionListItem(SessionEventArgsBase e)
{ {
lastSessionNumber++; lastSessionNumber++;
bool isTunnelConnect = e is TunnelConnectSessionEventArgs; bool isTunnelConnect = e is TunnelConnectSessionEventArgs;
......
...@@ -22,35 +22,17 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -22,35 +22,17 @@ namespace Titanium.Web.Proxy.EventArguments
/// A proxy session ends when client terminates connection to proxy /// A proxy session ends when client terminates connection to proxy
/// or when server terminates connection from proxy /// or when server terminates connection from proxy
/// </summary> /// </summary>
public class SessionEventArgs : EventArgs, IDisposable public class SessionEventArgs : SessionEventArgsBase
{ {
private static readonly byte[] emptyData = new byte[0]; private static readonly byte[] emptyData = new byte[0];
/// <summary>
/// Size of Buffers used by this object
/// </summary>
private readonly int bufferSize;
private readonly ExceptionHandler exceptionFunc;
/// <summary> /// <summary>
/// Backing field for corresponding public property /// Backing field for corresponding public property
/// </summary> /// </summary>
private bool reRequest; private bool reRequest;
/// <summary>
/// Holds a reference to client
/// </summary>
internal ProxyClient ProxyClient { get; }
private bool hasMulipartEventSubscribers => MultipartRequestPartSent != null; private bool hasMulipartEventSubscribers => MultipartRequestPartSent != null;
/// <summary>
/// Returns a unique Id for this request/response session
/// same as RequestId of WebSession
/// </summary>
public Guid Id => WebSession.RequestId;
/// <summary> /// <summary>
/// Should we send the request again /// Should we send the request again
/// </summary> /// </summary>
...@@ -68,42 +50,11 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -68,42 +50,11 @@ namespace Titanium.Web.Proxy.EventArguments
} }
} }
/// <summary>
/// Does this session uses SSL
/// </summary>
public bool IsHttps => WebSession.Request.IsHttps;
/// <summary>
/// Client End Point.
/// </summary>
public IPEndPoint ClientEndPoint => (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint;
/// <summary>
/// A web session corresponding to a single request/response sequence
/// within a proxy connection
/// </summary>
public HttpWebClient WebSession { get; }
/// <summary>
/// Are we using a custom upstream HTTP(S) proxy?
/// </summary>
public ExternalProxy CustomUpStreamProxyUsed { get; internal set; }
public event EventHandler<DataEventArgs> DataSent;
public event EventHandler<DataEventArgs> DataReceived;
/// <summary> /// <summary>
/// Occurs when multipart request part sent. /// Occurs when multipart request part sent.
/// </summary> /// </summary>
public event EventHandler<MultipartRequestPartSentEventArgs> MultipartRequestPartSent; public event EventHandler<MultipartRequestPartSentEventArgs> MultipartRequestPartSent;
public ProxyEndPoint LocalEndPoint { get; }
public bool IsTransparent => LocalEndPoint is TransparentProxyEndPoint;
public Exception Exception { get; internal set; }
/// <summary> /// <summary>
/// Constructor to initialize the proxy /// Constructor to initialize the proxy
/// </summary> /// </summary>
...@@ -113,32 +64,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -113,32 +64,8 @@ namespace Titanium.Web.Proxy.EventArguments
} }
protected SessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ExceptionHandler exceptionFunc, Request request) protected SessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ExceptionHandler exceptionFunc, Request request)
: base(bufferSize, endPoint, exceptionFunc, request)
{ {
this.bufferSize = bufferSize;
this.exceptionFunc = exceptionFunc;
ProxyClient = new ProxyClient();
WebSession = new HttpWebClient(bufferSize, request);
LocalEndPoint = endPoint;
WebSession.ProcessId = new Lazy<int>(() =>
{
if (RunTime.IsWindows)
{
var remoteEndPoint = (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint;
//If client is localhost get the process id
if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address))
{
return NetworkHelper.GetProcessIdFromPort(remoteEndPoint.Port, endPoint.IpV6Enabled);
}
//can't access process Id of remote request from remote machine
return -1;
}
throw new PlatformNotSupportedException();
});
} }
private CustomBufferedStream GetStream(bool isRequest) private CustomBufferedStream GetStream(bool isRequest)
...@@ -188,30 +115,6 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -188,30 +115,6 @@ namespace Titanium.Web.Proxy.EventArguments
WebSession.Response = new Response(); WebSession.Response = new Response();
} }
internal void OnDataSent(byte[] buffer, int offset, int count)
{
try
{
DataSent?.Invoke(this, new DataEventArgs(buffer, offset, count));
}
catch (Exception ex)
{
exceptionFunc(new Exception("Exception thrown in user event", ex));
}
}
internal void OnDataReceived(byte[] buffer, int offset, int count)
{
try
{
DataReceived?.Invoke(this, new DataEventArgs(buffer, offset, count));
}
catch (Exception ex)
{
exceptionFunc(new Exception("Exception thrown in user event", ex));
}
}
internal void OnMultipartRequestPartSent(string boundary, HeaderCollection headers) internal void OnMultipartRequestPartSent(string boundary, HeaderCollection headers)
{ {
try try
...@@ -220,7 +123,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -220,7 +123,7 @@ namespace Titanium.Web.Proxy.EventArguments
} }
catch (Exception ex) catch (Exception ex)
{ {
exceptionFunc(new Exception("Exception thrown in user event", ex)); ExceptionFunc(new Exception("Exception thrown in user event", ex));
} }
} }
...@@ -257,7 +160,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -257,7 +160,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
using (var bodyStream = new MemoryStream()) using (var bodyStream = new MemoryStream())
{ {
var writer = new HttpWriter(bodyStream, bufferSize); var writer = new HttpWriter(bodyStream, BufferSize);
if (isRequest) if (isRequest)
{ {
...@@ -282,7 +185,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -282,7 +185,7 @@ namespace Titanium.Web.Proxy.EventArguments
using (var bodyStream = new MemoryStream()) using (var bodyStream = new MemoryStream())
{ {
var writer = new HttpWriter(bodyStream, bufferSize); var writer = new HttpWriter(bodyStream, BufferSize);
await CopyBodyAsync(isRequest, writer, TransformationMode.None, null); await CopyBodyAsync(isRequest, writer, TransformationMode.None, null);
} }
} }
...@@ -303,8 +206,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -303,8 +206,8 @@ namespace Titanium.Web.Proxy.EventArguments
var reader = GetStreamReader(true); var reader = GetStreamReader(true);
string boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType); string boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType);
using (var copyStream = new CopyStream(reader, writer, bufferSize)) using (var copyStream = new CopyStream(reader, writer, BufferSize))
using (var copyStreamReader = new CustomBinaryReader(copyStream, bufferSize)) using (var copyStreamReader = new CustomBinaryReader(copyStream, BufferSize))
{ {
while (contentLength > copyStream.ReadBytes) while (contentLength > copyStream.ReadBytes)
{ {
...@@ -365,8 +268,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -365,8 +268,8 @@ namespace Titanium.Web.Proxy.EventArguments
try try
{ {
var bufStream = new CustomBufferedStream(s, bufferSize, true); var bufStream = new CustomBufferedStream(s, BufferSize, true);
reader = new CustomBinaryReader(bufStream, bufferSize); reader = new CustomBinaryReader(bufStream, BufferSize);
await writer.CopyBodyAsync(reader, false, -1, onCopy); await writer.CopyBodyAsync(reader, false, -1, onCopy);
} }
...@@ -388,7 +291,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -388,7 +291,7 @@ namespace Titanium.Web.Proxy.EventArguments
{ {
int bufferDataLength = 0; int bufferDataLength = 0;
var buffer = BufferPool.GetBuffer(bufferSize); var buffer = BufferPool.GetBuffer(BufferSize);
try try
{ {
int boundaryLength = boundary.Length + 4; int boundaryLength = boundary.Length + 4;
...@@ -684,16 +587,10 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -684,16 +587,10 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// implement any cleanup here /// implement any cleanup here
/// </summary> /// </summary>
public void Dispose() public override void Dispose()
{ {
CustomUpStreamProxyUsed = null;
DataSent = null;
DataReceived = null;
MultipartRequestPartSent = null; MultipartRequestPartSent = null;
Exception = null; base.Dispose();
WebSession.FinishSession();
} }
} }
} }
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Reflection;
using System.Threading.Tasks;
using StreamExtended.Helpers;
using StreamExtended.Network;
using Titanium.Web.Proxy.Decompression;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Http.Responses;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;
namespace Titanium.Web.Proxy.EventArguments
{
/// <summary>
/// Holds info related to a single proxy session (single request/response sequence)
/// A proxy session is bounded to a single connection from client
/// A proxy session ends when client terminates connection to proxy
/// or when server terminates connection from proxy
/// </summary>
public class SessionEventArgsBase : EventArgs, IDisposable
{
/// <summary>
/// Size of Buffers used by this object
/// </summary>
protected readonly int BufferSize;
protected readonly ExceptionHandler ExceptionFunc;
/// <summary>
/// Holds a reference to client
/// </summary>
internal ProxyClient ProxyClient { get; }
/// <summary>
/// Returns a unique Id for this request/response session
/// same as RequestId of WebSession
/// </summary>
public Guid Id => WebSession.RequestId;
/// <summary>
/// Does this session uses SSL
/// </summary>
public bool IsHttps => WebSession.Request.IsHttps;
/// <summary>
/// Client End Point.
/// </summary>
public IPEndPoint ClientEndPoint => (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint;
/// <summary>
/// A web session corresponding to a single request/response sequence
/// within a proxy connection
/// </summary>
public HttpWebClient WebSession { get; }
/// <summary>
/// Are we using a custom upstream HTTP(S) proxy?
/// </summary>
public ExternalProxy CustomUpStreamProxyUsed { get; internal set; }
public event EventHandler<DataEventArgs> DataSent;
public event EventHandler<DataEventArgs> DataReceived;
public ProxyEndPoint LocalEndPoint { get; }
public bool IsTransparent => LocalEndPoint is TransparentProxyEndPoint;
public Exception Exception { get; internal set; }
/// <summary>
/// Constructor to initialize the proxy
/// </summary>
internal SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, ExceptionHandler exceptionFunc)
: this(bufferSize, endPoint, exceptionFunc, null)
{
}
protected SessionEventArgsBase(int bufferSize, ProxyEndPoint endPoint, ExceptionHandler exceptionFunc, Request request)
{
this.BufferSize = bufferSize;
this.ExceptionFunc = exceptionFunc;
ProxyClient = new ProxyClient();
WebSession = new HttpWebClient(bufferSize, request);
LocalEndPoint = endPoint;
WebSession.ProcessId = new Lazy<int>(() =>
{
if (RunTime.IsWindows)
{
var remoteEndPoint = (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint;
//If client is localhost get the process id
if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address))
{
return NetworkHelper.GetProcessIdFromPort(remoteEndPoint.Port, endPoint.IpV6Enabled);
}
//can't access process Id of remote request from remote machine
return -1;
}
throw new PlatformNotSupportedException();
});
}
internal void OnDataSent(byte[] buffer, int offset, int count)
{
try
{
DataSent?.Invoke(this, new DataEventArgs(buffer, offset, count));
}
catch (Exception ex)
{
ExceptionFunc(new Exception("Exception thrown in user event", ex));
}
}
internal void OnDataReceived(byte[] buffer, int offset, int count)
{
try
{
DataReceived?.Invoke(this, new DataEventArgs(buffer, offset, count));
}
catch (Exception ex)
{
ExceptionFunc(new Exception("Exception thrown in user event", ex));
}
}
/// <summary>
/// implement any cleanup here
/// </summary>
public virtual void Dispose()
{
CustomUpStreamProxyUsed = null;
DataSent = null;
DataReceived = null;
Exception = null;
WebSession.FinishSession();
}
}
}
...@@ -4,10 +4,12 @@ using Titanium.Web.Proxy.Models; ...@@ -4,10 +4,12 @@ using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.EventArguments namespace Titanium.Web.Proxy.EventArguments
{ {
public class TunnelConnectSessionEventArgs : SessionEventArgs public class TunnelConnectSessionEventArgs : SessionEventArgsBase
{ {
public bool DecryptSsl { get; set; } = true; public bool DecryptSsl { get; set; } = true;
public bool BlockConnect { get; set; }
public bool IsHttpsConnect { get; internal set; } public bool IsHttpsConnect { get; internal set; }
internal TunnelConnectSessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ConnectRequest connectRequest, ExceptionHandler exceptionFunc) internal TunnelConnectSessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ConnectRequest connectRequest, ExceptionHandler exceptionFunc)
......
...@@ -17,13 +17,13 @@ namespace Titanium.Web.Proxy.Exceptions ...@@ -17,13 +17,13 @@ namespace Titanium.Web.Proxy.Exceptions
/// <param name="session">The <see cref="SessionEventArgs"/> instance containing the event data.</param> /// <param name="session">The <see cref="SessionEventArgs"/> instance containing the event data.</param>
/// <param name="innerException">Inner exception associated to upstream proxy authorization</param> /// <param name="innerException">Inner exception associated to upstream proxy authorization</param>
/// <param name="headers">Http's headers associated</param> /// <param name="headers">Http's headers associated</param>
internal ProxyAuthorizationException(string message, SessionEventArgs session, Exception innerException, IEnumerable<HttpHeader> headers) : base(message, innerException) internal ProxyAuthorizationException(string message, SessionEventArgsBase session, Exception innerException, IEnumerable<HttpHeader> headers) : base(message, innerException)
{ {
Session = session; Session = session;
Headers = headers; Headers = headers;
} }
public SessionEventArgs Session { get; } public SessionEventArgsBase Session { get; }
/// <summary> /// <summary>
/// Headers associated with the authorization exception /// Headers associated with the authorization exception
......
...@@ -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(SessionEventArgs session) private async Task<bool> CheckAuthorization(SessionEventArgsBase session)
{ {
if (AuthenticateUserFunc == null) if (AuthenticateUserFunc == null)
{ {
......
...@@ -177,7 +177,7 @@ namespace Titanium.Web.Proxy ...@@ -177,7 +177,7 @@ namespace Titanium.Web.Proxy
/// A callback to provide authentication credentials for up stream proxy this proxy is using for HTTP(S) requests /// A callback to provide authentication credentials for up stream proxy this proxy is using for HTTP(S) requests
/// return the ExternalProxy object with valid credentials /// return the ExternalProxy object with valid credentials
/// </summary> /// </summary>
public Func<SessionEventArgs, Task<ExternalProxy>> GetCustomUpStreamProxyFunc { get; set; } public Func<SessionEventArgsBase, Task<ExternalProxy>> GetCustomUpStreamProxyFunc { get; set; }
/// <summary> /// <summary>
/// Intercept request to server /// Intercept request to server
...@@ -581,7 +581,7 @@ namespace Titanium.Web.Proxy ...@@ -581,7 +581,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
/// <param name="sessionEventArgs">The <see cref="SessionEventArgs"/> instance containing the event data.</param> /// <param name="sessionEventArgs">The <see cref="SessionEventArgs"/> instance containing the event data.</param>
/// <returns><see cref="ExternalProxy"/> instance containing valid proxy configuration from PAC/WAPD scripts if any exists.</returns> /// <returns><see cref="ExternalProxy"/> instance containing valid proxy configuration from PAC/WAPD scripts if any exists.</returns>
private Task<ExternalProxy> GetSystemUpStreamProxy(SessionEventArgs sessionEventArgs) private Task<ExternalProxy> GetSystemUpStreamProxy(SessionEventArgsBase sessionEventArgs)
{ {
var proxy = systemProxyResolver.GetProxy(sessionEventArgs.WebSession.Request.RequestUri); var proxy = systemProxyResolver.GetProxy(sessionEventArgs.WebSession.Request.RequestUri);
return Task.FromResult(proxy); return Task.FromResult(proxy);
......
...@@ -81,6 +81,23 @@ namespace Titanium.Web.Proxy ...@@ -81,6 +81,23 @@ namespace Titanium.Web.Proxy
//filter out excluded host names //filter out excluded host names
bool decryptSsl = endPoint.DecryptSsl && connectArgs.DecryptSsl; bool decryptSsl = endPoint.DecryptSsl && connectArgs.DecryptSsl;
if (connectArgs.BlockConnect)
{
if (connectArgs.WebSession.Response.StatusCode == 0)
{
connectArgs.WebSession.Response = new Response
{
HttpVersion = HttpHeader.Version11,
StatusCode = (int)HttpStatusCode.Forbidden,
StatusDescription = "Forbidden",
};
}
//send the response
await clientStreamWriter.WriteResponseAsync(connectArgs.WebSession.Response);
return;
}
if (await CheckAuthorization(connectArgs) == false) if (await CheckAuthorization(connectArgs) == false)
{ {
await endPoint.InvokeBeforeTunnectConnectResponse(this, connectArgs, ExceptionFunc); await endPoint.InvokeBeforeTunnectConnectResponse(this, connectArgs, ExceptionFunc);
...@@ -630,7 +647,7 @@ namespace Titanium.Web.Proxy ...@@ -630,7 +647,7 @@ namespace Titanium.Web.Proxy
/// <param name="args"></param> /// <param name="args"></param>
/// <param name="isConnect"></param> /// <param name="isConnect"></param>
/// <returns></returns> /// <returns></returns>
private async Task<TcpConnection> GetServerConnection(SessionEventArgs args, bool isConnect) private async Task<TcpConnection> GetServerConnection(SessionEventArgsBase args, bool isConnect)
{ {
ExternalProxy customUpStreamProxy = null; ExternalProxy customUpStreamProxy = 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