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
});
}
private async Task ProxyServer_BeforeTunnelConnectResponse(object sender, SessionEventArgs e)
private async Task ProxyServer_BeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e)
{
await Dispatcher.InvokeAsync(() =>
{
......@@ -191,7 +191,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
});
}
private SessionListItem AddSession(SessionEventArgs e)
private SessionListItem AddSession(SessionEventArgsBase e)
{
var item = CreateSessionListItem(e);
Sessions.Add(item);
......@@ -199,7 +199,7 @@ namespace Titanium.Web.Proxy.Examples.Wpf
return item;
}
private SessionListItem CreateSessionListItem(SessionEventArgs e)
private SessionListItem CreateSessionListItem(SessionEventArgsBase e)
{
lastSessionNumber++;
bool isTunnelConnect = e is TunnelConnectSessionEventArgs;
......
......@@ -22,35 +22,17 @@ namespace Titanium.Web.Proxy.EventArguments
/// A proxy session ends when client terminates connection to proxy
/// or when server terminates connection from proxy
/// </summary>
public class SessionEventArgs : EventArgs, IDisposable
public class SessionEventArgs : SessionEventArgsBase
{
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>
/// Backing field for corresponding public property
/// </summary>
private bool reRequest;
/// <summary>
/// Holds a reference to client
/// </summary>
internal ProxyClient ProxyClient { get; }
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>
/// Should we send the request again
/// </summary>
......@@ -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>
/// Occurs when multipart request part sent.
/// </summary>
public event EventHandler<MultipartRequestPartSentEventArgs> MultipartRequestPartSent;
public ProxyEndPoint LocalEndPoint { get; }
public bool IsTransparent => LocalEndPoint is TransparentProxyEndPoint;
public Exception Exception { get; internal set; }
/// <summary>
/// Constructor to initialize the proxy
/// </summary>
......@@ -113,32 +64,8 @@ namespace Titanium.Web.Proxy.EventArguments
}
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)
......@@ -188,30 +115,6 @@ namespace Titanium.Web.Proxy.EventArguments
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)
{
try
......@@ -220,7 +123,7 @@ namespace Titanium.Web.Proxy.EventArguments
}
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
{
using (var bodyStream = new MemoryStream())
{
var writer = new HttpWriter(bodyStream, bufferSize);
var writer = new HttpWriter(bodyStream, BufferSize);
if (isRequest)
{
......@@ -282,7 +185,7 @@ namespace Titanium.Web.Proxy.EventArguments
using (var bodyStream = new MemoryStream())
{
var writer = new HttpWriter(bodyStream, bufferSize);
var writer = new HttpWriter(bodyStream, BufferSize);
await CopyBodyAsync(isRequest, writer, TransformationMode.None, null);
}
}
......@@ -303,8 +206,8 @@ namespace Titanium.Web.Proxy.EventArguments
var reader = GetStreamReader(true);
string boundary = HttpHelper.GetBoundaryFromContentType(request.ContentType);
using (var copyStream = new CopyStream(reader, writer, bufferSize))
using (var copyStreamReader = new CustomBinaryReader(copyStream, bufferSize))
using (var copyStream = new CopyStream(reader, writer, BufferSize))
using (var copyStreamReader = new CustomBinaryReader(copyStream, BufferSize))
{
while (contentLength > copyStream.ReadBytes)
{
......@@ -365,8 +268,8 @@ namespace Titanium.Web.Proxy.EventArguments
try
{
var bufStream = new CustomBufferedStream(s, bufferSize, true);
reader = new CustomBinaryReader(bufStream, bufferSize);
var bufStream = new CustomBufferedStream(s, BufferSize, true);
reader = new CustomBinaryReader(bufStream, BufferSize);
await writer.CopyBodyAsync(reader, false, -1, onCopy);
}
......@@ -388,7 +291,7 @@ namespace Titanium.Web.Proxy.EventArguments
{
int bufferDataLength = 0;
var buffer = BufferPool.GetBuffer(bufferSize);
var buffer = BufferPool.GetBuffer(BufferSize);
try
{
int boundaryLength = boundary.Length + 4;
......@@ -684,16 +587,10 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary>
/// implement any cleanup here
/// </summary>
public void Dispose()
public override void Dispose()
{
CustomUpStreamProxyUsed = null;
DataSent = null;
DataReceived = null;
MultipartRequestPartSent = null;
Exception = null;
WebSession.FinishSession();
base.Dispose();
}
}
}
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;
namespace Titanium.Web.Proxy.EventArguments
{
public class TunnelConnectSessionEventArgs : SessionEventArgs
public class TunnelConnectSessionEventArgs : SessionEventArgsBase
{
public bool DecryptSsl { get; set; } = true;
public bool BlockConnect { get; set; }
public bool IsHttpsConnect { get; internal set; }
internal TunnelConnectSessionEventArgs(int bufferSize, ProxyEndPoint endPoint, ConnectRequest connectRequest, ExceptionHandler exceptionFunc)
......
......@@ -17,13 +17,13 @@ namespace Titanium.Web.Proxy.Exceptions
/// <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="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;
Headers = headers;
}
public SessionEventArgs Session { get; }
public SessionEventArgsBase Session { get; }
/// <summary>
/// Headers associated with the authorization exception
......
......@@ -15,7 +15,7 @@ namespace Titanium.Web.Proxy
{
public partial class ProxyServer
{
private async Task<bool> CheckAuthorization(SessionEventArgs session)
private async Task<bool> CheckAuthorization(SessionEventArgsBase session)
{
if (AuthenticateUserFunc == null)
{
......
......@@ -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
/// return the ExternalProxy object with valid credentials
/// </summary>
public Func<SessionEventArgs, Task<ExternalProxy>> GetCustomUpStreamProxyFunc { get; set; }
public Func<SessionEventArgsBase, Task<ExternalProxy>> GetCustomUpStreamProxyFunc { get; set; }
/// <summary>
/// Intercept request to server
......@@ -581,7 +581,7 @@ namespace Titanium.Web.Proxy
/// </summary>
/// <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>
private Task<ExternalProxy> GetSystemUpStreamProxy(SessionEventArgs sessionEventArgs)
private Task<ExternalProxy> GetSystemUpStreamProxy(SessionEventArgsBase sessionEventArgs)
{
var proxy = systemProxyResolver.GetProxy(sessionEventArgs.WebSession.Request.RequestUri);
return Task.FromResult(proxy);
......
......@@ -81,6 +81,23 @@ namespace Titanium.Web.Proxy
//filter out excluded host names
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)
{
await endPoint.InvokeBeforeTunnectConnectResponse(this, connectArgs, ExceptionFunc);
......@@ -630,7 +647,7 @@ namespace Titanium.Web.Proxy
/// <param name="args"></param>
/// <param name="isConnect"></param>
/// <returns></returns>
private async Task<TcpConnection> GetServerConnection(SessionEventArgs args, bool isConnect)
private async Task<TcpConnection> GetServerConnection(SessionEventArgsBase args, bool isConnect)
{
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