Commit 46c59104 authored by Honfika's avatar Honfika

allow to get local endpoint in certificate validation/selection events #460

parent 4febcb05
...@@ -129,13 +129,21 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -129,13 +129,21 @@ namespace Titanium.Web.Proxy.Examples.Basic
private async Task<IExternalProxy> onGetCustomUpStreamProxyFunc(SessionEventArgsBase arg) private async Task<IExternalProxy> onGetCustomUpStreamProxyFunc(SessionEventArgsBase arg)
{ {
// this is just to show the functionality, provided values are junk // this is just to show the functionality, provided values are junk
return new ExternalProxy() { BypassLocalhost = false, HostName = "127.0.0.9", Port = 9090, Password = "fake", UserName = "fake", UseDefaultCredentials = false }; return new ExternalProxy
{
BypassLocalhost = false, HostName = "127.0.0.9", Port = 9090, Password = "fake", UserName = "fake",
UseDefaultCredentials = false
};
} }
private async Task<IExternalProxy> onCustomUpStreamProxyFailureFunc(SessionEventArgsBase arg) private async Task<IExternalProxy> onCustomUpStreamProxyFailureFunc(SessionEventArgsBase arg)
{ {
// this is just to show the functionality, provided values are junk // this is just to show the functionality, provided values are junk
return new ExternalProxy() { BypassLocalhost = false, HostName = "127.0.0.10", Port = 9191, Password = "fake2", UserName = "fake2", UseDefaultCredentials = false }; return new ExternalProxy
{
BypassLocalhost = false, HostName = "127.0.0.10", Port = 9191, Password = "fake2", UserName = "fake2",
UseDefaultCredentials = false
};
} }
private async Task onBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e) private async Task onBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
......
...@@ -12,17 +12,18 @@ namespace Titanium.Web.Proxy ...@@ -12,17 +12,18 @@ namespace Titanium.Web.Proxy
/// Call back to override server certificate validation /// Call back to override server certificate validation
/// </summary> /// </summary>
/// <param name="sender">The sender object.</param> /// <param name="sender">The sender object.</param>
/// <param name="sessionArgs">The http session.</param>
/// <param name="certificate">The remote certificate.</param> /// <param name="certificate">The remote certificate.</param>
/// <param name="chain">The certificate chain.</param> /// <param name="chain">The certificate chain.</param>
/// <param name="sslPolicyErrors">Ssl policy errors</param> /// <param name="sslPolicyErrors">Ssl policy errors</param>
/// <returns>Return true if valid certificate.</returns> /// <returns>Return true if valid certificate.</returns>
internal bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, internal bool ValidateServerCertificate(object sender, SessionEventArgsBase sessionArgs, X509Certificate certificate, X509Chain chain,
SslPolicyErrors sslPolicyErrors) SslPolicyErrors sslPolicyErrors)
{ {
// if user callback is registered then do it // if user callback is registered then do it
if (ServerCertificateValidationCallback != null) if (ServerCertificateValidationCallback != null)
{ {
var args = new CertificateValidationEventArgs(certificate, chain, sslPolicyErrors); var args = new CertificateValidationEventArgs(sessionArgs, certificate, chain, sslPolicyErrors);
// why is the sender null? // why is the sender null?
ServerCertificateValidationCallback.InvokeAsync(this, args, ExceptionFunc).Wait(); ServerCertificateValidationCallback.InvokeAsync(this, args, ExceptionFunc).Wait();
...@@ -43,12 +44,13 @@ namespace Titanium.Web.Proxy ...@@ -43,12 +44,13 @@ namespace Titanium.Web.Proxy
/// Call back to select client certificate used for mutual authentication /// Call back to select client certificate used for mutual authentication
/// </summary> /// </summary>
/// <param name="sender">The sender.</param> /// <param name="sender">The sender.</param>
/// <param name="sessionArgs">The http session.</param>
/// <param name="targetHost">The remote hostname.</param> /// <param name="targetHost">The remote hostname.</param>
/// <param name="localCertificates">Selected local certificates by SslStream.</param> /// <param name="localCertificates">Selected local certificates by SslStream.</param>
/// <param name="remoteCertificate">The remote certificate of server.</param> /// <param name="remoteCertificate">The remote certificate of server.</param>
/// <param name="acceptableIssuers">The acceptable issues for client certificate as listed by server.</param> /// <param name="acceptableIssuers">The acceptable issues for client certificate as listed by server.</param>
/// <returns></returns> /// <returns></returns>
internal X509Certificate? SelectClientCertificate(object sender, string targetHost, internal X509Certificate? SelectClientCertificate(object sender, SessionEventArgsBase sessionArgs, string targetHost,
X509CertificateCollection localCertificates, X509CertificateCollection localCertificates,
X509Certificate remoteCertificate, string[] acceptableIssuers) X509Certificate remoteCertificate, string[] acceptableIssuers)
{ {
...@@ -75,12 +77,8 @@ namespace Titanium.Web.Proxy ...@@ -75,12 +77,8 @@ namespace Titanium.Web.Proxy
// If user call back is registered // If user call back is registered
if (ClientCertificateSelectionCallback != null) if (ClientCertificateSelectionCallback != null)
{ {
var args = new CertificateSelectionEventArgs var args = new CertificateSelectionEventArgs(sessionArgs, targetHost, localCertificates, remoteCertificate, acceptableIssuers)
{ {
TargetHost = targetHost,
LocalCertificates = localCertificates,
RemoteCertificate = remoteCertificate,
AcceptableIssuers = acceptableIssuers,
ClientCertificate = clientCertificate ClientCertificate = clientCertificate
}; };
......
...@@ -8,30 +8,40 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -8,30 +8,40 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public class CertificateSelectionEventArgs : EventArgs public class CertificateSelectionEventArgs : EventArgs
{ {
/// <summary> public CertificateSelectionEventArgs(SessionEventArgsBase session, string targetHost,
/// The proxy server instance. X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers)
/// </summary> {
public object? Sender { get; internal set; } Session = session;
TargetHost = targetHost;
LocalCertificates = localCertificates;
RemoteCertificate = remoteCertificate;
AcceptableIssuers = acceptableIssuers;
}
/// <value>
/// The session.
/// </value>
public SessionEventArgsBase Session { get; }
/// <summary> /// <summary>
/// The remote hostname to which we are authenticating against. /// The remote hostname to which we are authenticating against.
/// </summary> /// </summary>
public string? TargetHost { get; internal set; } public string TargetHost { get; }
/// <summary> /// <summary>
/// Local certificates in store with matching issuers requested by TargetHost website. /// Local certificates in store with matching issuers requested by TargetHost website.
/// </summary> /// </summary>
public X509CertificateCollection? LocalCertificates { get; internal set; } public X509CertificateCollection LocalCertificates { get; }
/// <summary> /// <summary>
/// Certificate of the remote server. /// Certificate of the remote server.
/// </summary> /// </summary>
public X509Certificate? RemoteCertificate { get; internal set; } public X509Certificate RemoteCertificate { get; }
/// <summary> /// <summary>
/// Acceptable issuers as listed by remote server. /// Acceptable issuers as listed by remote server.
/// </summary> /// </summary>
public string[]? AcceptableIssuers { get; internal set; } public string[] AcceptableIssuers { get; }
/// <summary> /// <summary>
/// Client Certificate we selected. Set this value to override. /// Client Certificate we selected. Set this value to override.
......
...@@ -10,13 +10,19 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -10,13 +10,19 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
public class CertificateValidationEventArgs : EventArgs public class CertificateValidationEventArgs : EventArgs
{ {
public CertificateValidationEventArgs(X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) public CertificateValidationEventArgs(SessionEventArgsBase session, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{ {
Session = session;
Certificate = certificate; Certificate = certificate;
Chain = chain; Chain = chain;
SslPolicyErrors = sslPolicyErrors; SslPolicyErrors = sslPolicyErrors;
} }
/// <value>
/// The session.
/// </value>
public SessionEventArgsBase Session { get; }
/// <summary> /// <summary>
/// Server certificate. /// Server certificate.
/// </summary> /// </summary>
......
...@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
private bool reRequest; private bool reRequest;
private WebSocketDecoder webSocketDecoder; private WebSocketDecoder? webSocketDecoder;
/// <summary> /// <summary>
/// Is this session a HTTP/2 promise? /// Is this session a HTTP/2 promise?
...@@ -36,8 +36,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -36,8 +36,8 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// Constructor to initialize the proxy /// Constructor to initialize the proxy
/// </summary> /// </summary>
internal SessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, TcpClientConnection clientConnection, HttpClientStream clientStream, ConnectRequest? connectRequest, CancellationTokenSource cancellationTokenSource) internal SessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, HttpClientStream clientStream, ConnectRequest? connectRequest, CancellationTokenSource cancellationTokenSource)
: base(server, endPoint, clientConnection, clientStream, connectRequest, new Request(), cancellationTokenSource) : base(server, endPoint, clientStream, connectRequest, new Request(), cancellationTokenSource)
{ {
} }
......
...@@ -29,7 +29,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -29,7 +29,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// <summary> /// <summary>
/// Holds a reference to client /// Holds a reference to client
/// </summary> /// </summary>
internal TcpClientConnection ClientConnection { get; } internal TcpClientConnection ClientConnection => ClientStream.Connection;
internal HttpClientStream ClientStream { get; } internal HttpClientStream ClientStream { get; }
...@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy.EventArguments
/// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class. /// Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
/// </summary> /// </summary>
private protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint, private protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
TcpClientConnection clientConnection, HttpClientStream clientStream, ConnectRequest? connectRequest, Request request, CancellationTokenSource cancellationTokenSource) HttpClientStream clientStream, ConnectRequest? connectRequest, Request request, CancellationTokenSource cancellationTokenSource)
{ {
BufferPool = server.BufferPool; BufferPool = server.BufferPool;
ExceptionFunc = server.ExceptionFunc; ExceptionFunc = server.ExceptionFunc;
...@@ -58,9 +58,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -58,9 +58,8 @@ namespace Titanium.Web.Proxy.EventArguments
CancellationTokenSource = cancellationTokenSource; CancellationTokenSource = cancellationTokenSource;
ClientConnection = clientConnection;
ClientStream = clientStream; ClientStream = clientStream;
HttpClient = new HttpWebClient(connectRequest, request, new Lazy<int>(() => clientConnection.GetProcessId(endPoint))); HttpClient = new HttpWebClient(connectRequest, request, new Lazy<int>(() => clientStream.Connection.GetProcessId(endPoint)));
LocalEndPoint = endPoint; LocalEndPoint = endPoint;
EnableWinAuth = server.EnableWinAuth && isWindowsAuthenticationSupported; EnableWinAuth = server.EnableWinAuth && isWindowsAuthenticationSupported;
} }
......
...@@ -17,8 +17,8 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -17,8 +17,8 @@ namespace Titanium.Web.Proxy.EventArguments
private bool? isHttpsConnect; private bool? isHttpsConnect;
internal TunnelConnectSessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, ConnectRequest connectRequest, internal TunnelConnectSessionEventArgs(ProxyServer server, ProxyEndPoint endPoint, ConnectRequest connectRequest,
TcpClientConnection clientConnection, HttpClientStream clientStream, CancellationTokenSource cancellationTokenSource) HttpClientStream clientStream, CancellationTokenSource cancellationTokenSource)
: base(server, endPoint, clientConnection, clientStream, connectRequest, connectRequest, cancellationTokenSource) : base(server, endPoint, clientStream, connectRequest, connectRequest, cancellationTokenSource)
{ {
} }
......
...@@ -36,7 +36,7 @@ namespace Titanium.Web.Proxy ...@@ -36,7 +36,7 @@ namespace Titanium.Web.Proxy
var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
var clientStream = new HttpClientStream(clientConnection.GetStream(), BufferPool); var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool);
Task<TcpServerConnection>? prefetchConnectionTask = null; Task<TcpServerConnection>? prefetchConnectionTask = null;
bool closeServerConnection = false; bool closeServerConnection = false;
...@@ -72,8 +72,7 @@ namespace Titanium.Web.Proxy ...@@ -72,8 +72,7 @@ namespace Titanium.Web.Proxy
await HeaderParser.ReadHeaders(clientStream, connectRequest.Headers, cancellationToken); await HeaderParser.ReadHeaders(clientStream, connectRequest.Headers, cancellationToken);
connectArgs = new TunnelConnectSessionEventArgs(this, endPoint, connectRequest, connectArgs = new TunnelConnectSessionEventArgs(this, endPoint, connectRequest, clientStream, cancellationTokenSource);
clientConnection, clientStream, cancellationTokenSource);
clientStream.DataRead += (o, args) => connectArgs.OnDataSent(args.Buffer, args.Offset, args.Count); clientStream.DataRead += (o, args) => connectArgs.OnDataSent(args.Buffer, args.Offset, args.Count);
clientStream.DataWrite += (o, args) => connectArgs.OnDataReceived(args.Buffer, args.Offset, args.Count); clientStream.DataWrite += (o, args) => connectArgs.OnDataReceived(args.Buffer, args.Offset, args.Count);
...@@ -137,7 +136,7 @@ namespace Titanium.Web.Proxy ...@@ -137,7 +136,7 @@ namespace Titanium.Web.Proxy
if (decryptSsl && clientHelloInfo != null) if (decryptSsl && clientHelloInfo != null)
{ {
connectRequest.IsHttps = true; // todo: move this line to the previous "if" connectRequest.IsHttps = true; // todo: move this line to the previous "if"
clientConnection.SslProtocol = clientHelloInfo.SslProtocol; clientStream.Connection.SslProtocol = clientHelloInfo.SslProtocol;
bool http2Supported = false; bool http2Supported = false;
...@@ -221,11 +220,11 @@ namespace Titanium.Web.Proxy ...@@ -221,11 +220,11 @@ namespace Titanium.Web.Proxy
await sslStream.AuthenticateAsServerAsync(options, cancellationToken); await sslStream.AuthenticateAsServerAsync(options, cancellationToken);
#if NETSTANDARD2_1 #if NETSTANDARD2_1
clientConnection.NegotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol; clientStream.Connection.NegotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol;
#endif #endif
// HTTPS server created - we can now decrypt the client's traffic // HTTPS server created - we can now decrypt the client's traffic
clientStream = new HttpClientStream(sslStream, BufferPool); clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool);
sslStream = null; // clientStream was created, no need to keep SSL stream reference sslStream = null; // clientStream was created, no need to keep SSL stream reference
clientStream.DataRead += (o, args) => connectArgs.OnDecryptedDataSent(args.Buffer, args.Offset, args.Count); clientStream.DataRead += (o, args) => connectArgs.OnDecryptedDataSent(args.Buffer, args.Offset, args.Count);
...@@ -362,13 +361,13 @@ namespace Titanium.Web.Proxy ...@@ -362,13 +361,13 @@ namespace Titanium.Web.Proxy
var connectionPreface = new ReadOnlyMemory<byte>(Http2Helper.ConnectionPreface); var connectionPreface = new ReadOnlyMemory<byte>(Http2Helper.ConnectionPreface);
await connection.Stream.WriteAsync(connectionPreface, cancellationToken); await connection.Stream.WriteAsync(connectionPreface, cancellationToken);
await Http2Helper.SendHttp2(clientStream, connection.Stream, await Http2Helper.SendHttp2(clientStream, connection.Stream,
() => new SessionEventArgs(this, endPoint, clientConnection, clientStream, connectArgs?.HttpClient.ConnectRequest, cancellationTokenSource) () => new SessionEventArgs(this, endPoint, clientStream, connectArgs?.HttpClient.ConnectRequest, cancellationTokenSource)
{ {
UserData = connectArgs?.UserData UserData = connectArgs?.UserData
}, },
async args => { await onBeforeRequest(args); }, async args => { await onBeforeRequest(args); },
async args => { await onBeforeResponse(args); }, async args => { await onBeforeResponse(args); },
connectArgs.CancellationTokenSource, clientConnection.Id, ExceptionFunc); connectArgs.CancellationTokenSource, clientStream.Connection.Id, ExceptionFunc);
#endif #endif
} }
finally finally
...@@ -381,7 +380,7 @@ namespace Titanium.Web.Proxy ...@@ -381,7 +380,7 @@ namespace Titanium.Web.Proxy
calledRequestHandler = true; calledRequestHandler = true;
// Now create the request // Now create the request
await handleHttpSessionRequest(endPoint, clientConnection, clientStream, cancellationTokenSource, connectArgs, prefetchConnectionTask); await handleHttpSessionRequest(endPoint, clientStream, cancellationTokenSource, connectArgs, prefetchConnectionTask);
} }
catch (ProxyException e) catch (ProxyException e)
{ {
......
...@@ -6,7 +6,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -6,7 +6,7 @@ namespace Titanium.Web.Proxy.Extensions
{ {
internal static class StringExtensions internal static class StringExtensions
{ {
internal static bool EqualsIgnoreCase(this string str, string value) internal static bool EqualsIgnoreCase(this string str, string? value)
{ {
return str.Equals(value, StringComparison.CurrentCultureIgnoreCase); return str.Equals(value, StringComparison.CurrentCultureIgnoreCase);
} }
...@@ -16,12 +16,12 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -16,12 +16,12 @@ namespace Titanium.Web.Proxy.Extensions
return str.Equals(value, StringComparison.CurrentCultureIgnoreCase); return str.Equals(value, StringComparison.CurrentCultureIgnoreCase);
} }
internal static bool ContainsIgnoreCase(this string str, string value) internal static bool ContainsIgnoreCase(this string str, string? value)
{ {
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(str, value, CompareOptions.IgnoreCase) >= 0; return CultureInfo.CurrentCulture.CompareInfo.IndexOf(str, value, CompareOptions.IgnoreCase) >= 0;
} }
internal static int IndexOfIgnoreCase(this string str, string value) internal static int IndexOfIgnoreCase(this string str, string? value)
{ {
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(str, value, CompareOptions.IgnoreCase); return CultureInfo.CurrentCulture.CompareInfo.IndexOf(str, value, CompareOptions.IgnoreCase);
} }
......
...@@ -3,15 +3,19 @@ using System.IO; ...@@ -3,15 +3,19 @@ using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Http; using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Network.Tcp;
using Titanium.Web.Proxy.StreamExtended.BufferPool; using Titanium.Web.Proxy.StreamExtended.BufferPool;
namespace Titanium.Web.Proxy.Helpers namespace Titanium.Web.Proxy.Helpers
{ {
internal sealed class HttpClientStream : HttpStream internal sealed class HttpClientStream : HttpStream
{ {
internal HttpClientStream(Stream stream, IBufferPool bufferPool) public TcpClientConnection Connection { get; }
internal HttpClientStream(TcpClientConnection connection, Stream stream, IBufferPool bufferPool)
: base(stream, bufferPool) : base(stream, bufferPool)
{ {
Connection = connection;
} }
/// <summary> /// <summary>
......
...@@ -6,7 +6,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -6,7 +6,7 @@ namespace Titanium.Web.Proxy.Helpers
internal partial class NativeMethods internal partial class NativeMethods
{ {
// Keeps it from getting garbage collected // Keeps it from getting garbage collected
internal static ConsoleEventDelegate Handler; internal static ConsoleEventDelegate? Handler;
[DllImport("wininet.dll")] [DllImport("wininet.dll")]
internal static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, internal static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer,
......
...@@ -211,12 +211,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -211,12 +211,7 @@ namespace Titanium.Web.Proxy.Helpers
if (protocolType.HasValue) if (protocolType.HasValue)
{ {
var endPointParts = tmp.Substring(equalsIndex + 1).Split(':'); var endPointParts = tmp.Substring(equalsIndex + 1).Split(':');
return new HttpSystemProxyValue return new HttpSystemProxyValue(endPointParts[0], int.Parse(endPointParts[1]), protocolType.Value);
{
HostName = endPointParts[0],
Port = int.Parse(endPointParts[1]),
ProtocolType = protocolType.Value
};
} }
} }
......
...@@ -9,11 +9,18 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -9,11 +9,18 @@ namespace Titanium.Web.Proxy.Helpers
{ {
internal class HttpSystemProxyValue internal class HttpSystemProxyValue
{ {
internal string HostName { get; set; } internal string HostName { get; }
internal int Port { get; set; } internal int Port { get; }
internal ProxyProtocolType ProtocolType { get; set; } internal ProxyProtocolType ProtocolType { get; }
public HttpSystemProxyValue(string hostName, int port, ProxyProtocolType protocolType)
{
HostName = hostName;
Port = port;
ProtocolType = protocolType;
}
public override string ToString() public override string ToString()
{ {
...@@ -56,7 +63,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -56,7 +63,7 @@ namespace Titanium.Web.Proxy.Helpers
AppDomain.CurrentDomain.ProcessExit += (o, args) => RestoreOriginalSettings(); AppDomain.CurrentDomain.ProcessExit += (o, args) => RestoreOriginalSettings();
if (Environment.UserInteractive && NativeMethods.GetConsoleWindow() != IntPtr.Zero) if (Environment.UserInteractive && NativeMethods.GetConsoleWindow() != IntPtr.Zero)
{ {
NativeMethods.Handler = eventType => var handler = new NativeMethods.ConsoleEventDelegate(eventType =>
{ {
if (eventType != 2) if (eventType != 2)
{ {
...@@ -65,10 +72,11 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -65,10 +72,11 @@ namespace Titanium.Web.Proxy.Helpers
RestoreOriginalSettings(); RestoreOriginalSettings();
return false; return false;
}; });
NativeMethods.Handler = handler;
// On Console exit make sure we also exit the proxy // On Console exit make sure we also exit the proxy
NativeMethods.SetConsoleCtrlHandler(NativeMethods.Handler, true); NativeMethods.SetConsoleCtrlHandler(handler, true);
} }
} }
...@@ -95,22 +103,12 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -95,22 +103,12 @@ namespace Titanium.Web.Proxy.Helpers
existingSystemProxyValues.RemoveAll(x => (protocolType & x.ProtocolType) != 0); existingSystemProxyValues.RemoveAll(x => (protocolType & x.ProtocolType) != 0);
if ((protocolType & ProxyProtocolType.Http) != 0) if ((protocolType & ProxyProtocolType.Http) != 0)
{ {
existingSystemProxyValues.Add(new HttpSystemProxyValue existingSystemProxyValues.Add(new HttpSystemProxyValue(hostname, port, ProxyProtocolType.Http));
{
HostName = hostname,
ProtocolType = ProxyProtocolType.Http,
Port = port
});
} }
if ((protocolType & ProxyProtocolType.Https) != 0) if ((protocolType & ProxyProtocolType.Https) != 0)
{ {
existingSystemProxyValues.Add(new HttpSystemProxyValue existingSystemProxyValues.Add(new HttpSystemProxyValue(hostname, port, ProxyProtocolType.Https));
{
HostName = hostname,
ProtocolType = ProxyProtocolType.Https,
Port = port
});
} }
reg.DeleteValue(regAutoConfigUrl, false); reg.DeleteValue(regAutoConfigUrl, false);
......
...@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.Http ...@@ -26,7 +26,7 @@ namespace Titanium.Web.Proxy.Http
return String.AsSpan().EqualsIgnoreCase(value); return String.AsSpan().EqualsIgnoreCase(value);
} }
internal bool Equals(string value) internal bool Equals(string? value)
{ {
return String.EqualsIgnoreCase(value); return String.EqualsIgnoreCase(value);
} }
......
...@@ -141,7 +141,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -141,7 +141,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
} }
Size -= removed.Size; Size -= removed.Size;
headerFields[tail++] = null; headerFields[tail++] = null!;
if (tail == headerFields.Length) if (tail == headerFields.Length)
{ {
tail = 0; tail = 0;
...@@ -157,7 +157,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack ...@@ -157,7 +157,7 @@ namespace Titanium.Web.Proxy.Http2.Hpack
{ {
while (tail != head) while (tail != head)
{ {
headerFields[tail++] = null; headerFields[tail++] = null!;
if (tail == headerFields.Length) if (tail == headerFields.Length)
{ {
tail = 0; tail = 0;
......
...@@ -139,14 +139,14 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -139,14 +139,14 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <summary> /// <summary>
/// Create a server connection. /// Create a server connection.
/// </summary> /// </summary>
/// <param name="server">The proxy server.</param> /// <param name="proxyServer">The proxy server.</param>
/// <param name="session">The session event arguments.</param> /// <param name="session">The session event arguments.</param>
/// <param name="isConnect">Is this a CONNECT request.</param> /// <param name="isConnect">Is this a CONNECT request.</param>
/// <param name="applicationProtocol"></param> /// <param name="applicationProtocol"></param>
/// <param name="noCache">if set to <c>true</c> [no cache].</param> /// <param name="noCache">if set to <c>true</c> [no cache].</param>
/// <param name="cancellationToken">The cancellation token for this async task.</param> /// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns> /// <returns></returns>
internal Task<TcpServerConnection> GetServerConnection(ProxyServer server, SessionEventArgsBase session, bool isConnect, internal Task<TcpServerConnection> GetServerConnection(ProxyServer proxyServer, SessionEventArgsBase session, bool isConnect,
SslApplicationProtocol applicationProtocol, bool noCache, CancellationToken cancellationToken) SslApplicationProtocol applicationProtocol, bool noCache, CancellationToken cancellationToken)
{ {
List<SslApplicationProtocol>? applicationProtocols = null; List<SslApplicationProtocol>? applicationProtocols = null;
...@@ -155,28 +155,28 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -155,28 +155,28 @@ namespace Titanium.Web.Proxy.Network.Tcp
applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol }; applicationProtocols = new List<SslApplicationProtocol> { applicationProtocol };
} }
return GetServerConnection(server, session, isConnect, applicationProtocols, noCache, cancellationToken); return GetServerConnection(proxyServer, session, isConnect, applicationProtocols, noCache, cancellationToken);
} }
/// <summary> /// <summary>
/// Create a server connection. /// Create a server connection.
/// </summary> /// </summary>
/// <param name="server">The proxy server.</param> /// <param name="proxyServer">The proxy server.</param>
/// <param name="session">The session event arguments.</param> /// <param name="session">The session event arguments.</param>
/// <param name="isConnect">Is this a CONNECT request.</param> /// <param name="isConnect">Is this a CONNECT request.</param>
/// <param name="applicationProtocols"></param> /// <param name="applicationProtocols"></param>
/// <param name="noCache">if set to <c>true</c> [no cache].</param> /// <param name="noCache">if set to <c>true</c> [no cache].</param>
/// <param name="cancellationToken">The cancellation token for this async task.</param> /// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns> /// <returns></returns>
internal async Task<TcpServerConnection> GetServerConnection(ProxyServer server, SessionEventArgsBase session, bool isConnect, internal async Task<TcpServerConnection> GetServerConnection(ProxyServer proxyServer, SessionEventArgsBase session, bool isConnect,
List<SslApplicationProtocol>? applicationProtocols, bool noCache, CancellationToken cancellationToken) List<SslApplicationProtocol>? applicationProtocols, bool noCache, CancellationToken cancellationToken)
{ {
IExternalProxy? customUpStreamProxy = null; IExternalProxy? customUpStreamProxy = null;
bool isHttps = session.IsHttps; bool isHttps = session.IsHttps;
if (server.GetCustomUpStreamProxyFunc != null) if (proxyServer.GetCustomUpStreamProxyFunc != null)
{ {
customUpStreamProxy = await server.GetCustomUpStreamProxyFunc(session); customUpStreamProxy = await proxyServer.GetCustomUpStreamProxyFunc(session);
} }
session.CustomUpStreamProxyUsed = customUpStreamProxy; session.CustomUpStreamProxyUsed = customUpStreamProxy;
...@@ -207,37 +207,36 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -207,37 +207,36 @@ namespace Titanium.Web.Proxy.Network.Tcp
} }
return await GetServerConnection( return await GetServerConnection(
host, proxyServer, host, port,
port,
session.HttpClient.Request.HttpVersion, session.HttpClient.Request.HttpVersion,
isHttps, applicationProtocols, isConnect, isHttps, applicationProtocols, isConnect,
server, session, session.HttpClient.UpStreamEndPoint ?? server.UpStreamEndPoint, session, session.HttpClient.UpStreamEndPoint ?? proxyServer.UpStreamEndPoint,
customUpStreamProxy ?? (isHttps ? server.UpStreamHttpsProxy : server.UpStreamHttpProxy), customUpStreamProxy ?? (isHttps ? proxyServer.UpStreamHttpsProxy : proxyServer.UpStreamHttpProxy),
noCache, cancellationToken); noCache, cancellationToken);
} }
/// <summary> /// <summary>
/// Gets a TCP connection to server from connection pool. /// Gets a TCP connection to server from connection pool.
/// </summary> /// </summary>
/// <param name="proxyServer">The current ProxyServer instance.</param>
/// <param name="remoteHostName">The remote hostname.</param> /// <param name="remoteHostName">The remote hostname.</param>
/// <param name="remotePort">The remote port.</param> /// <param name="remotePort">The remote port.</param>
/// <param name="httpVersion">The http version to use.</param> /// <param name="httpVersion">The http version to use.</param>
/// <param name="isHttps">Is this a HTTPS request.</param> /// <param name="isHttps">Is this a HTTPS request.</param>
/// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param> /// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param>
/// <param name="isConnect">Is this a CONNECT request.</param> /// <param name="isConnect">Is this a CONNECT request.</param>
/// <param name="proxyServer">The current ProxyServer instance.</param> /// <param name="sessionArgs">The session event arguments.</param>
/// <param name="session">The session.</param>
/// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param> /// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param>
/// <param name="externalProxy">The external proxy to make request via.</param> /// <param name="externalProxy">The external proxy to make request via.</param>
/// <param name="noCache">Not from cache/create new connection.</param> /// <param name="noCache">Not from cache/create new connection.</param>
/// <param name="cancellationToken">The cancellation token for this async task.</param> /// <param name="cancellationToken">The cancellation token for this async task.</param>
/// <returns></returns> /// <returns></returns>
internal async Task<TcpServerConnection> GetServerConnection(string remoteHostName, int remotePort, internal async Task<TcpServerConnection> GetServerConnection(ProxyServer proxyServer, string remoteHostName, int remotePort,
Version httpVersion, bool isHttps, List<SslApplicationProtocol>? applicationProtocols, bool isConnect, Version httpVersion, bool isHttps, List<SslApplicationProtocol>? applicationProtocols, bool isConnect,
ProxyServer proxyServer, SessionEventArgsBase? session, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy, SessionEventArgsBase sessionArgs, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy,
bool noCache, CancellationToken cancellationToken) bool noCache, CancellationToken cancellationToken)
{ {
var sslProtocol = session?.ClientConnection.SslProtocol ?? SslProtocols.None; var sslProtocol = sessionArgs.ClientConnection.SslProtocol;
var cacheKey = GetConnectionCacheKey(remoteHostName, remotePort, var cacheKey = GetConnectionCacheKey(remoteHostName, remotePort,
isHttps, applicationProtocols, upStreamEndPoint, externalProxy); isHttps, applicationProtocols, upStreamEndPoint, externalProxy);
...@@ -264,7 +263,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -264,7 +263,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
} }
var connection = await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol, var connection = await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol,
applicationProtocols, isConnect, proxyServer, session, upStreamEndPoint, externalProxy, cacheKey, cancellationToken); applicationProtocols, isConnect, proxyServer, sessionArgs, upStreamEndPoint, externalProxy, cacheKey, cancellationToken);
return connection; return connection;
} }
...@@ -280,7 +279,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -280,7 +279,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param> /// <param name="applicationProtocols">The list of HTTPS application level protocol to negotiate if needed.</param>
/// <param name="isConnect">Is this a CONNECT request.</param> /// <param name="isConnect">Is this a CONNECT request.</param>
/// <param name="proxyServer">The current ProxyServer instance.</param> /// <param name="proxyServer">The current ProxyServer instance.</param>
/// <param name="session">The http session.</param> /// <param name="sessionArgs">The http session.</param>
/// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param> /// <param name="upStreamEndPoint">The local upstream endpoint to make request via.</param>
/// <param name="externalProxy">The external proxy to make request via.</param> /// <param name="externalProxy">The external proxy to make request via.</param>
/// <param name="cacheKey">The connection cache key</param> /// <param name="cacheKey">The connection cache key</param>
...@@ -288,7 +287,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -288,7 +287,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <returns></returns> /// <returns></returns>
private async Task<TcpServerConnection> createServerConnection(string remoteHostName, int remotePort, private async Task<TcpServerConnection> createServerConnection(string remoteHostName, int remotePort,
Version httpVersion, bool isHttps, SslProtocols sslProtocol, List<SslApplicationProtocol>? applicationProtocols, bool isConnect, Version httpVersion, bool isHttps, SslProtocols sslProtocol, List<SslApplicationProtocol>? applicationProtocols, bool isConnect,
ProxyServer proxyServer, SessionEventArgsBase? session, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy, string cacheKey, ProxyServer proxyServer, SessionEventArgsBase sessionArgs, IPEndPoint? upStreamEndPoint, IExternalProxy? externalProxy, string cacheKey,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
// deny connection to proxy end points to avoid infinite connection loop. // deny connection to proxy end points to avoid infinite connection loop.
...@@ -346,14 +345,14 @@ retry: ...@@ -346,14 +345,14 @@ retry:
throw new Exception($"Could not resolve the hostname {hostname}"); throw new Exception($"Could not resolve the hostname {hostname}");
} }
if (session != null) if (sessionArgs != null)
{ {
session.TimeLine["Dns Resolved"] = DateTime.Now; sessionArgs.TimeLine["Dns Resolved"] = DateTime.Now;
} }
Array.Sort(ipAddresses, (x, y) => x.AddressFamily.CompareTo(y.AddressFamily)); Array.Sort(ipAddresses, (x, y) => x.AddressFamily.CompareTo(y.AddressFamily));
Exception lastException = null; Exception? lastException = null;
for (int i = 0; i < ipAddresses.Length; i++) for (int i = 0; i < ipAddresses.Length; i++)
{ {
try try
...@@ -427,23 +426,23 @@ retry: ...@@ -427,23 +426,23 @@ retry:
if (tcpClient == null) if (tcpClient == null)
{ {
if (session != null && proxyServer.CustomUpStreamProxyFailureFunc != null) if (sessionArgs != null && proxyServer.CustomUpStreamProxyFailureFunc != null)
{ {
var newUpstreamProxy = await proxyServer.CustomUpStreamProxyFailureFunc(session); var newUpstreamProxy = await proxyServer.CustomUpStreamProxyFailureFunc(sessionArgs);
if (newUpstreamProxy != null) if (newUpstreamProxy != null)
{ {
session.CustomUpStreamProxyUsed = newUpstreamProxy; sessionArgs.CustomUpStreamProxyUsed = newUpstreamProxy;
session.TimeLine["Retrying Upstream Proxy Connection"] = DateTime.Now; sessionArgs.TimeLine["Retrying Upstream Proxy Connection"] = DateTime.Now;
return await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol, applicationProtocols, isConnect, proxyServer, session, upStreamEndPoint, externalProxy, cacheKey, cancellationToken); return await createServerConnection(remoteHostName, remotePort, httpVersion, isHttps, sslProtocol, applicationProtocols, isConnect, proxyServer, sessionArgs, upStreamEndPoint, externalProxy, cacheKey, cancellationToken);
} }
} }
throw new Exception($"Could not establish connection to {hostname}", lastException); throw new Exception($"Could not establish connection to {hostname}", lastException);
} }
if (session != null) if (sessionArgs != null)
{ {
session.TimeLine["Connection Established"] = DateTime.Now; sessionArgs.TimeLine["Connection Established"] = DateTime.Now;
} }
await proxyServer.InvokeConnectionCreateEvent(tcpClient, false); await proxyServer.InvokeConnectionCreateEvent(tcpClient, false);
...@@ -483,8 +482,13 @@ retry: ...@@ -483,8 +482,13 @@ retry:
if (isHttps) if (isHttps)
{ {
var sslStream = new SslStream(stream, false, proxyServer.ValidateServerCertificate, var sslStream = new SslStream(stream, false,
proxyServer.SelectClientCertificate); (sender, certificate, chain, sslPolicyErrors) =>
proxyServer.ValidateServerCertificate(sender, sessionArgs, certificate, chain,
sslPolicyErrors),
(sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) =>
proxyServer.SelectClientCertificate(sender, sessionArgs, targetHost, localCertificates,
remoteCertificate, acceptableIssuers));
stream = new HttpServerStream(sslStream, proxyServer.BufferPool); stream = new HttpServerStream(sslStream, proxyServer.BufferPool);
var options = new SslClientAuthenticationOptions var options = new SslClientAuthenticationOptions
...@@ -500,9 +504,9 @@ retry: ...@@ -500,9 +504,9 @@ retry:
negotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol; negotiatedApplicationProtocol = sslStream.NegotiatedApplicationProtocol;
#endif #endif
if (session != null) if (sessionArgs != null)
{ {
session.TimeLine["HTTPS Established"] = DateTime.Now; sessionArgs.TimeLine["HTTPS Established"] = DateTime.Now;
} }
} }
} }
......
...@@ -705,7 +705,7 @@ namespace Titanium.Web.Proxy ...@@ -705,7 +705,7 @@ namespace Titanium.Web.Proxy
throw new ArgumentNullException(nameof(endPoint)); throw new ArgumentNullException(nameof(endPoint));
} }
if (ProxyEndPoints.Contains(endPoint) == false) if (!ProxyEndPoints.Contains(endPoint))
{ {
throw new Exception("Cannot set endPoints not added to proxy as system proxy"); throw new Exception("Cannot set endPoints not added to proxy as system proxy");
} }
...@@ -739,7 +739,7 @@ namespace Titanium.Web.Proxy ...@@ -739,7 +739,7 @@ namespace Titanium.Web.Proxy
try try
{ {
// based on end point type call appropriate request handlers // based on end point type call appropriate request handlers
tcpClient = endPoint.Listener.EndAcceptTcpClient(asyn); tcpClient = endPoint.Listener!.EndAcceptTcpClient(asyn);
tcpClient.NoDelay = NoDelay; tcpClient.NoDelay = NoDelay;
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)
...@@ -763,7 +763,7 @@ namespace Titanium.Web.Proxy ...@@ -763,7 +763,7 @@ namespace Titanium.Web.Proxy
} }
// Get the listener that handles the client request. // Get the listener that handles the client request.
endPoint.Listener.BeginAcceptTcpClient(onAcceptConnection, endPoint); endPoint.Listener!.BeginAcceptTcpClient(onAcceptConnection, endPoint);
} }
...@@ -825,7 +825,7 @@ namespace Titanium.Web.Proxy ...@@ -825,7 +825,7 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
private void quitListen(ProxyEndPoint endPoint) private void quitListen(ProxyEndPoint endPoint)
{ {
endPoint.Listener.Stop(); endPoint.Listener!.Stop();
endPoint.Listener.Server.Dispose(); endPoint.Listener.Server.Dispose();
} }
......
...@@ -29,13 +29,12 @@ namespace Titanium.Web.Proxy ...@@ -29,13 +29,12 @@ namespace Titanium.Web.Proxy
/// client/server abruptly terminates connection or by normal HTTP termination. /// client/server abruptly terminates connection or by normal HTTP termination.
/// </summary> /// </summary>
/// <param name="endPoint">The proxy endpoint.</param> /// <param name="endPoint">The proxy endpoint.</param>
/// <param name="clientConnection">The client connection.</param>
/// <param name="clientStream">The client stream.</param> /// <param name="clientStream">The client stream.</param>
/// <param name="cancellationTokenSource">The cancellation token source for this async task.</param> /// <param name="cancellationTokenSource">The cancellation token source for this async task.</param>
/// <param name="connectArgs">The Connect request if this is a HTTPS request from explicit endpoint.</param> /// <param name="connectArgs">The Connect request if this is a HTTPS request from explicit endpoint.</param>
/// <param name="prefetchConnectionTask">Prefetched server connection for current client using Connect/SNI headers.</param> /// <param name="prefetchConnectionTask">Prefetched server connection for current client using Connect/SNI headers.</param>
private async Task handleHttpSessionRequest(ProxyEndPoint endPoint, TcpClientConnection clientConnection, private async Task handleHttpSessionRequest(ProxyEndPoint endPoint, HttpClientStream clientStream,
HttpClientStream clientStream, CancellationTokenSource cancellationTokenSource, TunnelConnectSessionEventArgs? connectArgs = null, CancellationTokenSource cancellationTokenSource, TunnelConnectSessionEventArgs? connectArgs = null,
Task<TcpServerConnection>? prefetchConnectionTask = null) Task<TcpServerConnection>? prefetchConnectionTask = null)
{ {
var connectRequest = connectArgs?.HttpClient.ConnectRequest; var connectRequest = connectArgs?.HttpClient.ConnectRequest;
...@@ -64,7 +63,7 @@ namespace Titanium.Web.Proxy ...@@ -64,7 +63,7 @@ namespace Titanium.Web.Proxy
return; return;
} }
var args = new SessionEventArgs(this, endPoint, clientConnection, clientStream, connectRequest, cancellationTokenSource) var args = new SessionEventArgs(this, endPoint, clientStream, connectRequest, cancellationTokenSource)
{ {
UserData = connectArgs?.UserData UserData = connectArgs?.UserData
}; };
...@@ -163,7 +162,7 @@ namespace Titanium.Web.Proxy ...@@ -163,7 +162,7 @@ namespace Titanium.Web.Proxy
// or when prefetch task has a unexpectedly different connection. // or when prefetch task has a unexpectedly different connection.
if (connection != null if (connection != null
&& (await tcpConnectionFactory.GetConnectionCacheKey(this, args, && (await tcpConnectionFactory.GetConnectionCacheKey(this, args,
clientConnection.NegotiatedApplicationProtocol) clientStream.Connection.NegotiatedApplicationProtocol)
!= connection.CacheKey)) != connection.CacheKey))
{ {
await tcpConnectionFactory.Release(connection); await tcpConnectionFactory.Release(connection);
...@@ -171,7 +170,7 @@ namespace Titanium.Web.Proxy ...@@ -171,7 +170,7 @@ namespace Titanium.Web.Proxy
} }
var result = await handleHttpSessionRequest(args, connection, var result = await handleHttpSessionRequest(args, connection,
clientConnection.NegotiatedApplicationProtocol, clientStream.Connection.NegotiatedApplicationProtocol,
cancellationToken, cancellationTokenSource); cancellationToken, cancellationTokenSource);
// update connection to latest used // update connection to latest used
......
...@@ -33,7 +33,7 @@ namespace Titanium.Web.Proxy ...@@ -33,7 +33,7 @@ namespace Titanium.Web.Proxy
var cancellationTokenSource = new CancellationTokenSource(); var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token; var cancellationToken = cancellationTokenSource.Token;
var clientStream = new HttpClientStream(clientConnection.GetStream(), BufferPool); var clientStream = new HttpClientStream(clientConnection, clientConnection.GetStream(), BufferPool);
SslStream? sslStream = null; SslStream? sslStream = null;
...@@ -58,7 +58,7 @@ namespace Titanium.Web.Proxy ...@@ -58,7 +58,7 @@ namespace Titanium.Web.Proxy
if (endPoint.DecryptSsl && args.DecryptSsl) if (endPoint.DecryptSsl && args.DecryptSsl)
{ {
clientConnection.SslProtocol = clientHelloInfo.SslProtocol; clientStream.Connection.SslProtocol = clientHelloInfo.SslProtocol;
// do client authentication using certificate // do client authentication using certificate
X509Certificate2? certificate = null; X509Certificate2? certificate = null;
...@@ -74,14 +74,13 @@ namespace Titanium.Web.Proxy ...@@ -74,14 +74,13 @@ namespace Titanium.Web.Proxy
await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false); await sslStream.AuthenticateAsServerAsync(certificate, false, SslProtocols.Tls, false);
// HTTPS server created - we can now decrypt the client's traffic // HTTPS server created - we can now decrypt the client's traffic
clientStream = new HttpClientStream(sslStream, BufferPool); clientStream = new HttpClientStream(clientStream.Connection, sslStream, BufferPool);
sslStream = null; // clientStream was created, no need to keep SSL stream reference sslStream = null; // clientStream was created, no need to keep SSL stream reference
} }
catch (Exception e) catch (Exception e)
{ {
var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false); var certName = certificate?.GetNameInfo(X509NameType.SimpleName, false);
var session = new SessionEventArgs(this, endPoint, clientConnection, clientStream, null, var session = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource);
cancellationTokenSource);
throw new ProxyConnectException( throw new ProxyConnectException(
$"Couldn't authenticate host '{httpsHostName}' with certificate '{certName}'.", e, session); $"Couldn't authenticate host '{httpsHostName}' with certificate '{certName}'.", e, session);
} }
...@@ -89,9 +88,10 @@ namespace Titanium.Web.Proxy ...@@ -89,9 +88,10 @@ namespace Titanium.Web.Proxy
} }
else else
{ {
var connection = await tcpConnectionFactory.GetServerConnection(httpsHostName, endPoint.Port, var sessionArgs = new SessionEventArgs(this, endPoint, clientStream, null, cancellationTokenSource);
var connection = await tcpConnectionFactory.GetServerConnection(this, httpsHostName, endPoint.Port,
HttpHeader.VersionUnknown, false, null, HttpHeader.VersionUnknown, false, null,
true, this, null, UpStreamEndPoint, true, sessionArgs, UpStreamEndPoint,
UpStreamHttpsProxy, true, cancellationToken); UpStreamHttpsProxy, true, cancellationToken);
try try
...@@ -131,7 +131,7 @@ namespace Titanium.Web.Proxy ...@@ -131,7 +131,7 @@ namespace Titanium.Web.Proxy
// HTTPS server created - we can now decrypt the client's traffic // HTTPS server created - we can now decrypt the client's traffic
// Now create the request // Now create the request
await handleHttpSessionRequest(endPoint, clientConnection, clientStream, cancellationTokenSource); await handleHttpSessionRequest(endPoint, clientStream, cancellationTokenSource);
} }
catch (ProxyException e) catch (ProxyException e)
{ {
......
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