Commit 54cfea8f authored by Jehonathan Thomas's avatar Jehonathan Thomas Committed by GitHub

Merge pull request #221 from justcoding121/develop

Beta Merge
parents e82ad51e 84660ddd
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
...@@ -18,6 +17,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -18,6 +17,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
public ProxyTestController() public ProxyTestController()
{ {
proxyServer = new ProxyServer(); proxyServer = new ProxyServer();
proxyServer.ExceptionFunc = exception => Console.WriteLine(exception.Message);
proxyServer.TrustRootCertificate = true; proxyServer.TrustRootCertificate = true;
//optionally set the Certificate Engine //optionally set the Certificate Engine
...@@ -99,7 +99,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -99,7 +99,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
{ {
Console.WriteLine(e.WebSession.Request.Url); Console.WriteLine(e.WebSession.Request.Url);
////read request headers //read request headers
var requestHeaders = e.WebSession.Request.RequestHeaders; var requestHeaders = e.WebSession.Request.RequestHeaders;
var method = e.WebSession.Request.Method.ToUpper(); var method = e.WebSession.Request.Method.ToUpper();
...@@ -128,6 +128,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -128,6 +128,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
"</body>" + "</body>" +
"</html>"); "</html>");
} }
//Redirect example //Redirect example
if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org")) if (e.WebSession.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
{ {
...@@ -143,6 +144,7 @@ namespace Titanium.Web.Proxy.Examples.Basic ...@@ -143,6 +144,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
//access request body by looking up the shared dictionary using requestId //access request body by looking up the shared dictionary using requestId
var requestBody = requestBodyHistory[e.Id]; var requestBody = requestBodyHistory[e.Id];
} }
//read response headers //read response headers
var responseHeaders = e.WebSession.Response.ResponseHeaders; var responseHeaders = e.WebSession.Response.ResponseHeaders;
......
using System; using System;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net; using System.Net;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments; using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models; using Titanium.Web.Proxy.Models;
...@@ -28,14 +27,13 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -28,14 +27,13 @@ namespace Titanium.Web.Proxy.IntegrationTests
{ {
var response = client.GetAsync(new Uri(testUrl)).Result; var response = client.GetAsync(new Uri(testUrl)).Result;
} }
} }
private HttpClient CreateHttpClient(string url, int localProxyPort) private HttpClient CreateHttpClient(string url, int localProxyPort)
{ {
var handler = new HttpClientHandler var handler = new HttpClientHandler
{ {
Proxy = new WebProxy(string.Format("http://localhost:{0}", localProxyPort), false), Proxy = new WebProxy($"http://localhost:{localProxyPort}", false),
UseProxy = true, UseProxy = true,
}; };
...@@ -47,7 +45,7 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -47,7 +45,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
public class ProxyTestController public class ProxyTestController
{ {
private ProxyServer proxyServer; private readonly ProxyServer proxyServer;
public ProxyTestController() public ProxyTestController()
{ {
...@@ -64,7 +62,6 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -64,7 +62,6 @@ namespace Titanium.Web.Proxy.IntegrationTests
var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, proxyPort, true); var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, proxyPort, true);
//An explicit endpoint is where the client knows about the existance of a proxy //An explicit endpoint is where the client knows about the existance of a proxy
//So client sends request in a proxy friendly manner //So client sends request in a proxy friendly manner
proxyServer.AddEndPoint(explicitEndPoint); proxyServer.AddEndPoint(explicitEndPoint);
...@@ -73,7 +70,6 @@ namespace Titanium.Web.Proxy.IntegrationTests ...@@ -73,7 +70,6 @@ namespace Titanium.Web.Proxy.IntegrationTests
foreach (var endPoint in proxyServer.ProxyEndPoints) foreach (var endPoint in proxyServer.ProxyEndPoints)
Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ", Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port); endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
} }
public void Stop() public void Stop()
......
...@@ -20,8 +20,7 @@ namespace Titanium.Web.Proxy.UnitTests ...@@ -20,8 +20,7 @@ namespace Titanium.Web.Proxy.UnitTests
{ {
var tasks = new List<Task>(); var tasks = new List<Task>();
var mgr = new CertificateManager(CertificateEngine.DefaultWindows, "Titanium", "Titanium Root Certificate Authority", var mgr = new CertificateManager(new Lazy<Action<Exception>>(() => (e => { })).Value);
new Lazy<Action<Exception>>(() => (e => { })).Value);
mgr.ClearIdleCertificates(1); mgr.ClearIdleCertificates(1);
......
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BC/@EntryIndexedValue">BC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=dda2ffa1_002D435c_002D4111_002D88eb_002D1a7c93c382f0/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Property (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="PROPERTY" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String></wpf:ResourceDictionary> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=dda2ffa1_002D435c_002D4111_002D88eb_002D1a7c93c382f0/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Property (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="PROPERTY" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String></wpf:ResourceDictionary>
\ No newline at end of file
...@@ -21,7 +21,7 @@ namespace Titanium.Web.Proxy.Decompression ...@@ -21,7 +21,7 @@ namespace Titanium.Web.Proxy.Decompression
int read; int read;
while ((read = await decompressor.ReadAsync(buffer, 0, buffer.Length)) > 0) while ((read = await decompressor.ReadAsync(buffer, 0, buffer.Length)) > 0)
{ {
await output.WriteAsync(buffer, 0, read); output.Write(buffer, 0, read);
} }
return output.ToArray(); return output.ToArray();
......
...@@ -19,8 +19,9 @@ namespace Titanium.Web.Proxy.Decompression ...@@ -19,8 +19,9 @@ namespace Titanium.Web.Proxy.Decompression
int read; int read;
while ((read = await decompressor.ReadAsync(buffer, 0, buffer.Length)) > 0) while ((read = await decompressor.ReadAsync(buffer, 0, buffer.Length)) > 0)
{ {
await output.WriteAsync(buffer, 0, read); output.Write(buffer, 0, read);
} }
return output.ToArray(); return output.ToArray();
} }
} }
......
...@@ -46,7 +46,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -46,7 +46,7 @@ namespace Titanium.Web.Proxy.Extensions
while (totalbytesRead < totalBytesToRead) while (totalbytesRead < totalBytesToRead)
{ {
var buffer = await streamReader.ReadBytesAsync(bufferSize, bytesToRead); var buffer = await streamReader.ReadBytesAsync(bytesToRead);
if (buffer.Length == 0) if (buffer.Length == 0)
{ {
...@@ -81,7 +81,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -81,7 +81,7 @@ namespace Titanium.Web.Proxy.Extensions
if (chunkSize != 0) if (chunkSize != 0)
{ {
var buffer = await clientStreamReader.ReadBytesAsync(bufferSize, chunkSize); var buffer = await clientStreamReader.ReadBytesAsync(chunkSize);
await stream.WriteAsync(buffer, 0, buffer.Length); await stream.WriteAsync(buffer, 0, buffer.Length);
//chunk trail //chunk trail
await clientStreamReader.ReadLineAsync(); await clientStreamReader.ReadLineAsync();
...@@ -179,7 +179,7 @@ namespace Titanium.Web.Proxy.Extensions ...@@ -179,7 +179,7 @@ namespace Titanium.Web.Proxy.Extensions
if (chunkSize != 0) if (chunkSize != 0)
{ {
var buffer = await inStreamReader.ReadBytesAsync(bufferSize, chunkSize); var buffer = await inStreamReader.ReadBytesAsync(chunkSize);
var chunkHeadBytes = Encoding.ASCII.GetBytes(chunkSize.ToString("x2")); var chunkHeadBytes = Encoding.ASCII.GetBytes(chunkSize.ToString("x2"));
......
using System; using System.Globalization;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Extensions namespace Titanium.Web.Proxy.Extensions
{ {
......
...@@ -19,18 +19,18 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -19,18 +19,18 @@ namespace Titanium.Web.Proxy.Helpers
private readonly Encoding encoding; private readonly Encoding encoding;
[ThreadStatic] [ThreadStatic]
private static byte[] staticBuffer; private static byte[] staticBufferField;
private byte[] buffer private byte[] staticBuffer
{ {
get get
{ {
if (staticBuffer == null || staticBuffer.Length != bufferSize) if (staticBufferField == null || staticBufferField.Length != bufferSize)
{ {
staticBuffer = new byte[bufferSize]; staticBufferField = new byte[bufferSize];
} }
return staticBuffer; return staticBufferField;
} }
} }
...@@ -56,7 +56,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -56,7 +56,7 @@ namespace Titanium.Web.Proxy.Helpers
int bufferDataLength = 0; int bufferDataLength = 0;
// try to use the thread static buffer, usually it is enough // try to use the thread static buffer, usually it is enough
var buffer = this.buffer; var buffer = staticBuffer;
while (stream.DataAvailable || await stream.FillBufferAsync()) while (stream.DataAvailable || await stream.FillBufferAsync())
{ {
...@@ -117,22 +117,16 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -117,22 +117,16 @@ namespace Titanium.Web.Proxy.Helpers
/// <summary> /// <summary>
/// Read the specified number of raw bytes from the base stream /// Read the specified number of raw bytes from the base stream
/// </summary> /// </summary>
/// <param name="bufferSize"></param>
/// <param name="totalBytesToRead"></param> /// <param name="totalBytesToRead"></param>
/// <returns></returns> /// <returns></returns>
internal async Task<byte[]> ReadBytesAsync(int bufferSize, long totalBytesToRead) internal async Task<byte[]> ReadBytesAsync(long totalBytesToRead)
{ {
int bytesToRead = bufferSize; int bytesToRead = bufferSize;
if (totalBytesToRead < bufferSize) if (totalBytesToRead < bufferSize)
bytesToRead = (int)totalBytesToRead; bytesToRead = (int)totalBytesToRead;
var buffer = this.buffer; var buffer = staticBuffer;
if (bytesToRead > buffer.Length)
{
buffer = new byte[bytesToRead];
}
int bytesRead; int bytesRead;
var totalBytesRead = 0; var totalBytesRead = 0;
......
...@@ -16,7 +16,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -16,7 +16,7 @@ namespace Titanium.Web.Proxy.Helpers
{ {
private readonly Stream baseStream; private readonly Stream baseStream;
private readonly byte[] buffer; private readonly byte[] streamBuffer;
private int bufferLength; private int bufferLength;
...@@ -30,7 +30,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -30,7 +30,7 @@ namespace Titanium.Web.Proxy.Helpers
public CustomBufferedStream(Stream baseStream, int bufferSize) public CustomBufferedStream(Stream baseStream, int bufferSize)
{ {
this.baseStream = baseStream; this.baseStream = baseStream;
buffer = new byte[bufferSize]; streamBuffer = new byte[bufferSize];
} }
/// <summary> /// <summary>
...@@ -84,7 +84,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -84,7 +84,7 @@ namespace Titanium.Web.Proxy.Helpers
int available = Math.Min(bufferLength, count); int available = Math.Min(bufferLength, count);
if (available > 0) if (available > 0)
{ {
Buffer.BlockCopy(this.buffer, bufferPos, buffer, offset, available); Buffer.BlockCopy(streamBuffer, bufferPos, buffer, offset, available);
bufferPos += available; bufferPos += available;
bufferLength -= available; bufferLength -= available;
} }
...@@ -120,7 +120,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -120,7 +120,7 @@ namespace Titanium.Web.Proxy.Helpers
if (bufferLength > 0) if (bufferLength > 0)
{ {
int available = Math.Min(bufferLength, count); int available = Math.Min(bufferLength, count);
Buffer.BlockCopy(this.buffer, bufferPos, buffer, offset, available); Buffer.BlockCopy(streamBuffer, bufferPos, buffer, offset, available);
bufferPos += available; bufferPos += available;
bufferLength -= available; bufferLength -= available;
return new ReadAsyncResult(available); return new ReadAsyncResult(available);
...@@ -167,7 +167,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -167,7 +167,7 @@ namespace Titanium.Web.Proxy.Helpers
{ {
if (bufferLength > 0) if (bufferLength > 0)
{ {
await destination.WriteAsync(buffer, bufferPos, bufferLength, cancellationToken); await destination.WriteAsync(streamBuffer, bufferPos, bufferLength, cancellationToken);
} }
await baseStream.CopyToAsync(destination, bufferSize, cancellationToken); await baseStream.CopyToAsync(destination, bufferSize, cancellationToken);
...@@ -256,7 +256,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -256,7 +256,7 @@ namespace Titanium.Web.Proxy.Helpers
int available = Math.Min(bufferLength, count); int available = Math.Min(bufferLength, count);
if (available > 0) if (available > 0)
{ {
Buffer.BlockCopy(this.buffer, bufferPos, buffer, offset, available); Buffer.BlockCopy(streamBuffer, bufferPos, buffer, offset, available);
bufferPos += available; bufferPos += available;
bufferLength -= available; bufferLength -= available;
} }
...@@ -283,7 +283,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -283,7 +283,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
bufferLength--; bufferLength--;
return buffer[bufferPos++]; return streamBuffer[bufferPos++];
} }
public byte ReadByteFromBuffer() public byte ReadByteFromBuffer()
...@@ -294,7 +294,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -294,7 +294,7 @@ namespace Titanium.Web.Proxy.Helpers
} }
bufferLength--; bufferLength--;
return buffer[bufferPos++]; return streamBuffer[bufferPos++];
} }
/// <summary> /// <summary>
...@@ -390,7 +390,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -390,7 +390,7 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary> /// </summary>
public bool FillBuffer() public bool FillBuffer()
{ {
bufferLength = baseStream.Read(buffer, 0, buffer.Length); bufferLength = baseStream.Read(streamBuffer, 0, streamBuffer.Length);
bufferPos = 0; bufferPos = 0;
return bufferLength > 0; return bufferLength > 0;
} }
...@@ -411,7 +411,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -411,7 +411,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns></returns> /// <returns></returns>
public async Task<bool> FillBufferAsync(CancellationToken cancellationToken) public async Task<bool> FillBufferAsync(CancellationToken cancellationToken)
{ {
bufferLength = await baseStream.ReadAsync(buffer, 0, buffer.Length, cancellationToken); bufferLength = await baseStream.ReadAsync(streamBuffer, 0, streamBuffer.Length, cancellationToken);
bufferPos = 0; bufferPos = 0;
return bufferLength > 0; return bufferLength > 0;
} }
......
...@@ -55,7 +55,7 @@ namespace Titanium.Web.Proxy.Helpers ...@@ -55,7 +55,7 @@ namespace Titanium.Web.Proxy.Helpers
{ {
localhost = Dns.GetHostEntry(Dns.GetHostName()); localhost = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = null; IPAddress ipAddress;
if (IPAddress.TryParse(hostName, out ipAddress)) if (IPAddress.TryParse(hostName, out ipAddress))
isLocalhost = localhost.AddressList.Any(x => x.Equals(ipAddress)); isLocalhost = localhost.AddressList.Any(x => x.Equals(ipAddress));
......
...@@ -21,9 +21,9 @@ namespace Titanium.Web.Proxy.Models ...@@ -21,9 +21,9 @@ namespace Titanium.Web.Proxy.Models
/// <param name="enableSsl"></param> /// <param name="enableSsl"></param>
protected ProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl) protected ProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl)
{ {
this.IpAddress = ipAddress; IpAddress = ipAddress;
this.Port = port; Port = port;
this.EnableSsl = enableSsl; EnableSsl = enableSsl;
} }
/// <summary> /// <summary>
...@@ -55,8 +55,8 @@ namespace Titanium.Web.Proxy.Models ...@@ -55,8 +55,8 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public class ExplicitProxyEndPoint : ProxyEndPoint public class ExplicitProxyEndPoint : ProxyEndPoint
{ {
internal List<Regex> excludedHttpsHostNameRegex; internal List<Regex> ExcludedHttpsHostNameRegexList;
internal List<Regex> includedHttpsHostNameRegex; internal List<Regex> IncludedHttpsHostNameRegexList;
internal bool IsSystemHttpProxy { get; set; } internal bool IsSystemHttpProxy { get; set; }
...@@ -67,7 +67,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -67,7 +67,7 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public IEnumerable<string> ExcludedHttpsHostNameRegex public IEnumerable<string> ExcludedHttpsHostNameRegex
{ {
get { return excludedHttpsHostNameRegex?.Select(x => x.ToString()).ToList(); } get { return ExcludedHttpsHostNameRegexList?.Select(x => x.ToString()).ToList(); }
set set
{ {
if (IncludedHttpsHostNameRegex != null) if (IncludedHttpsHostNameRegex != null)
...@@ -75,7 +75,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -75,7 +75,7 @@ namespace Titanium.Web.Proxy.Models
throw new ArgumentException("Cannot set excluded when included is set"); throw new ArgumentException("Cannot set excluded when included is set");
} }
excludedHttpsHostNameRegex = value?.Select(x=>new Regex(x, RegexOptions.Compiled)).ToList(); ExcludedHttpsHostNameRegexList = value?.Select(x=>new Regex(x, RegexOptions.Compiled)).ToList();
} }
} }
...@@ -84,7 +84,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -84,7 +84,7 @@ namespace Titanium.Web.Proxy.Models
/// </summary> /// </summary>
public IEnumerable<string> IncludedHttpsHostNameRegex public IEnumerable<string> IncludedHttpsHostNameRegex
{ {
get { return includedHttpsHostNameRegex?.Select(x => x.ToString()).ToList(); } get { return IncludedHttpsHostNameRegexList?.Select(x => x.ToString()).ToList(); }
set set
{ {
if (ExcludedHttpsHostNameRegex != null) if (ExcludedHttpsHostNameRegex != null)
...@@ -92,7 +92,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -92,7 +92,7 @@ namespace Titanium.Web.Proxy.Models
throw new ArgumentException("Cannot set included when excluded is set"); throw new ArgumentException("Cannot set included when excluded is set");
} }
includedHttpsHostNameRegex = value?.Select(x => new Regex(x, RegexOptions.Compiled)).ToList(); IncludedHttpsHostNameRegexList = value?.Select(x => new Regex(x, RegexOptions.Compiled)).ToList();
} }
} }
...@@ -136,7 +136,7 @@ namespace Titanium.Web.Proxy.Models ...@@ -136,7 +136,7 @@ namespace Titanium.Web.Proxy.Models
public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl) public TransparentProxyEndPoint(IPAddress ipAddress, int port, bool enableSsl)
: base(ipAddress, port, enableSsl) : base(ipAddress, port, enableSsl)
{ {
this.GenericCertificateName = "localhost"; GenericCertificateName = "localhost";
} }
} }
......
...@@ -181,7 +181,7 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -181,7 +181,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
} }
}); });
manualResetEvent.Wait(TimeSpan.FromMinutes(1), cancellationToken: cancellationToken); manualResetEvent.Wait(TimeSpan.FromMinutes(1), cancellationToken);
} }
return certificate; return certificate;
......
...@@ -31,14 +31,48 @@ namespace Titanium.Web.Proxy.Network ...@@ -31,14 +31,48 @@ namespace Titanium.Web.Proxy.Network
/// </summary> /// </summary>
internal class CertificateManager : IDisposable internal class CertificateManager : IDisposable
{ {
public CertificateEngine Engine
{
get { return engine; }
set
{
//For Mono only Bouncy Castle is supported
if (RunTime.IsRunningOnMono())
{
value = CertificateEngine.BouncyCastle;
}
if (value != engine)
{
certEngine = null;
engine = value;
}
if (certEngine == null)
{
certEngine = engine == CertificateEngine.BouncyCastle ?
(ICertificateMaker) new BCCertificateMaker()
: new WinCertificateMaker();
}
}
}
private const string defaultRootCertificateIssuer = "Titanium"; private const string defaultRootCertificateIssuer = "Titanium";
private const string defaultRootRootCertificateName = "Titanium Root Certificate Authority"; private const string defaultRootRootCertificateName = "Titanium Root Certificate Authority";
private readonly ICertificateMaker certEngine; private CertificateEngine engine;
private ICertificateMaker certEngine;
private string issuer;
private string rootCertificateName;
private bool clearCertificates { get; set; } private bool clearCertificates { get; set; }
private X509Certificate2 rootCertificate;
/// <summary> /// <summary>
/// Cache dictionary /// Cache dictionary
/// </summary> /// </summary>
...@@ -46,36 +80,56 @@ namespace Titanium.Web.Proxy.Network ...@@ -46,36 +80,56 @@ namespace Titanium.Web.Proxy.Network
private readonly Action<Exception> exceptionFunc; private readonly Action<Exception> exceptionFunc;
internal string Issuer { get; } internal string Issuer
internal string RootCertificateName { get; }
internal X509Certificate2 RootCertificate { get; set; }
internal CertificateManager(CertificateEngine engine,
string issuer,
string rootCertificateName,
Action<Exception> exceptionFunc)
{ {
this.exceptionFunc = exceptionFunc; get { return issuer ?? defaultRootCertificateIssuer; }
set
{
issuer = value;
ClearRootCertificate();
}
}
//For Mono only Bouncy Castle is supported internal string RootCertificateName
if (RunTime.IsRunningOnMono()
|| engine == CertificateEngine.BouncyCastle)
{ {
certEngine = new BCCertificateMaker(); get { return rootCertificateName ?? defaultRootRootCertificateName; }
set
{
rootCertificateName = value;
ClearRootCertificate();
} }
else }
internal X509Certificate2 RootCertificate
{
get { return rootCertificate; }
set
{ {
certEngine = new WinCertificateMaker(); ClearRootCertificate();
rootCertificate = value;
} }
}
/// <summary>
/// Is the root certificate used by this proxy is valid?
/// </summary>
internal bool CertValidated => RootCertificate != null;
Issuer = issuer ?? defaultRootCertificateIssuer; internal CertificateManager(Action<Exception> exceptionFunc)
RootCertificateName = rootCertificateName ?? defaultRootRootCertificateName; {
this.exceptionFunc = exceptionFunc;
Engine = CertificateEngine.DefaultWindows;
certificateCache = new ConcurrentDictionary<string, CachedCertificate>(); certificateCache = new ConcurrentDictionary<string, CachedCertificate>();
} }
private void ClearRootCertificate()
{
certificateCache.Clear();
rootCertificate = null;
}
private string GetRootCertificatePath() private string GetRootCertificatePath()
{ {
var assemblyLocation = System.Reflection.Assembly.GetExecutingAssembly().Location; var assemblyLocation = System.Reflection.Assembly.GetExecutingAssembly().Location;
...@@ -150,14 +204,13 @@ namespace Titanium.Web.Proxy.Network ...@@ -150,14 +204,13 @@ namespace Titanium.Web.Proxy.Network
/// <summary> /// <summary>
/// Trusts the root certificate. /// Trusts the root certificate.
/// </summary> /// </summary>
/// <param name="exceptionFunc"></param> internal void TrustRootCertificate()
internal void TrustRootCertificate(Action<Exception> exceptionFunc)
{ {
//current user //current user
TrustRootCertificate(StoreLocation.CurrentUser, exceptionFunc); TrustRootCertificate(StoreLocation.CurrentUser);
//current system //current system
TrustRootCertificate(StoreLocation.LocalMachine, exceptionFunc); TrustRootCertificate(StoreLocation.LocalMachine);
} }
/// <summary> /// <summary>
...@@ -246,10 +299,8 @@ namespace Titanium.Web.Proxy.Network ...@@ -246,10 +299,8 @@ namespace Titanium.Web.Proxy.Network
/// 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="storeLocation"></param> /// <param name="storeLocation"></param>
/// <param name="exceptionFunc"></param>
/// <returns></returns> /// <returns></returns>
internal void TrustRootCertificate(StoreLocation storeLocation, internal void TrustRootCertificate(StoreLocation storeLocation)
Action<Exception> exceptionFunc)
{ {
if (RootCertificate == null) if (RootCertificate == null)
{ {
......
...@@ -16,6 +16,7 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -16,6 +16,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
internal ExternalProxy UpStreamHttpsProxy { get; set; } internal ExternalProxy UpStreamHttpsProxy { get; set; }
internal string HostName { get; set; } internal string HostName { get; set; }
internal int Port { get; set; } internal int Port { get; set; }
internal bool IsHttps { get; set; } internal bool IsHttps { get; set; }
...@@ -58,7 +59,6 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -58,7 +59,6 @@ namespace Titanium.Web.Proxy.Network.Tcp
TcpClient.LingerState = new LingerOption(true, 0); TcpClient.LingerState = new LingerOption(true, 0);
TcpClient.Close(); TcpClient.Close();
} }
} }
} }
...@@ -19,11 +19,6 @@ namespace Titanium.Web.Proxy ...@@ -19,11 +19,6 @@ namespace Titanium.Web.Proxy
/// </summary> /// </summary>
public partial class ProxyServer : IDisposable public partial class ProxyServer : IDisposable
{ {
/// <summary>
/// Is the root certificate used by this proxy is valid?
/// </summary>
private bool? certValidated { get; set; }
/// <summary> /// <summary>
/// Is the proxy currently running /// Is the proxy currently running
/// </summary> /// </summary>
...@@ -85,11 +80,7 @@ namespace Titanium.Web.Proxy ...@@ -85,11 +80,7 @@ namespace Titanium.Web.Proxy
public string RootCertificateIssuerName public string RootCertificateIssuerName
{ {
get { return certificateManager.Issuer; } get { return certificateManager.Issuer; }
set set { certificateManager.RootCertificateName = value; }
{
CreateCertificateManager(certificateManager.RootCertificateName, value);
certValidated = null;
}
} }
/// <summary> /// <summary>
...@@ -102,11 +93,7 @@ namespace Titanium.Web.Proxy ...@@ -102,11 +93,7 @@ namespace Titanium.Web.Proxy
public string RootCertificateName public string RootCertificateName
{ {
get { return certificateManager.RootCertificateName; } get { return certificateManager.RootCertificateName; }
set set { certificateManager.Issuer = value; }
{
CreateCertificateManager(value, certificateManager.Issuer);
certValidated = null;
}
} }
/// <summary> /// <summary>
...@@ -132,7 +119,11 @@ namespace Titanium.Web.Proxy ...@@ -132,7 +119,11 @@ namespace Titanium.Web.Proxy
/// Optionally set to BouncyCastle /// Optionally set to BouncyCastle
/// Mono only support BouncyCastle and it is the default /// Mono only support BouncyCastle and it is the default
/// </summary> /// </summary>
public CertificateEngine CertificateEngine { get; set; } public CertificateEngine CertificateEngine
{
get { return certificateManager.Engine; }
set { certificateManager.Engine = value; }
}
/// <summary> /// <summary>
/// Does this proxy uses the HTTP protocol 100 continue behaviour strictly? /// Does this proxy uses the HTTP protocol 100 continue behaviour strictly?
...@@ -272,7 +263,16 @@ namespace Titanium.Web.Proxy ...@@ -272,7 +263,16 @@ namespace Titanium.Web.Proxy
new FireFoxProxySettingsManager(); new FireFoxProxySettingsManager();
#endif #endif
CreateCertificateManager(rootCertificateName, rootCertificateIssuerName); certificateManager = new CertificateManager(ExceptionFunc);
if (rootCertificateName != null)
{
RootCertificateName = rootCertificateName;
}
if (rootCertificateIssuerName != null)
{
RootCertificateIssuerName = rootCertificateIssuerName;
}
} }
/// <summary> /// <summary>
...@@ -369,7 +369,7 @@ namespace Titanium.Web.Proxy ...@@ -369,7 +369,7 @@ namespace Titanium.Web.Proxy
EnsureRootCertificate(); EnsureRootCertificate();
//If certificate was trusted by the machine //If certificate was trusted by the machine
if (certValidated == true) if (certificateManager.CertValidated)
{ {
systemProxySettingsManager.SetHttpsProxy( systemProxySettingsManager.SetHttpsProxy(
Equals(endPoint.IpAddress, IPAddress.Any) | Equals(endPoint.IpAddress, IPAddress.Any) |
...@@ -557,21 +557,15 @@ namespace Titanium.Web.Proxy ...@@ -557,21 +557,15 @@ namespace Titanium.Web.Proxy
} }
private void CreateCertificateManager(string rootCertificateName, string rootCertificateIssuerName)
{
certificateManager = new CertificateManager(CertificateEngine,
rootCertificateIssuerName, rootCertificateName, ExceptionFunc);
}
private void EnsureRootCertificate() private void EnsureRootCertificate()
{ {
if (!certValidated.HasValue) if (!certificateManager.CertValidated)
{ {
certValidated = certificateManager.CreateTrustedRootCertificate(); certificateManager.CreateTrustedRootCertificate();
if (TrustRootCertificate) if (TrustRootCertificate)
{ {
certificateManager.TrustRootCertificate(ExceptionFunc); certificateManager.TrustRootCertificate();
} }
} }
} }
......
...@@ -75,12 +75,12 @@ namespace Titanium.Web.Proxy ...@@ -75,12 +75,12 @@ namespace Titanium.Web.Proxy
if (endPoint.ExcludedHttpsHostNameRegex != null) if (endPoint.ExcludedHttpsHostNameRegex != null)
{ {
excluded = endPoint.excludedHttpsHostNameRegex.Any(x => x.IsMatch(httpRemoteUri.Host)); excluded = endPoint.ExcludedHttpsHostNameRegexList.Any(x => x.IsMatch(httpRemoteUri.Host));
} }
if (endPoint.IncludedHttpsHostNameRegex != null) if (endPoint.IncludedHttpsHostNameRegex != null)
{ {
excluded = !endPoint.includedHttpsHostNameRegex.Any(x => x.IsMatch(httpRemoteUri.Host)); excluded = !endPoint.IncludedHttpsHostNameRegexList.Any(x => x.IsMatch(httpRemoteUri.Host));
} }
List<HttpHeader> connectRequestHeaders = null; List<HttpHeader> connectRequestHeaders = 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