Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ public class ProxyTestController
public ProxyTestController()
{
proxyServer = new ProxyServer();

//generate root certificate without storing it in file system
//proxyServer.CertificateEngine = Network.CertificateEngine.BouncyCastle;
//proxyServer.CertificateManager.CreateTrustedRootCertificate(false);
//proxyServer.CertificateManager.TrustRootCertificate();

proxyServer.ExceptionFunc = exception => Console.WriteLine(exception.Message);
proxyServer.TrustRootCertificate = true;

Expand Down Expand Up @@ -92,6 +98,9 @@ public void Stop()
proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;

proxyServer.Stop();

//remove the generated certificates
//proxyServer.CertificateManager.RemoveTrustedRootCertificates();
}

//intecept & cancel redirect or update requests
Expand Down
69 changes: 62 additions & 7 deletions Titanium.Web.Proxy/Network/CertificateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ public enum CertificateEngine
/// <summary>
/// A class to manage SSL certificates used by this proxy server
/// </summary>
internal class CertificateManager : IDisposable
public class CertificateManager : IDisposable
{
public CertificateEngine Engine
internal CertificateEngine Engine
{
get { return engine; }
set
Expand Down Expand Up @@ -164,10 +164,13 @@ internal X509Certificate2 LoadRootCertificate()
/// <summary>
/// Attempts to create a RootCertificate
/// </summary>
/// <returns>true if succeeded, else false</returns>
internal bool CreateTrustedRootCertificate()
/// <param name="persistToFile">if set to <c>true</c> try to load/save the certificate from rootCert.pfx.</param>
/// <returns>
/// true if succeeded, else false
/// </returns>
public bool CreateTrustedRootCertificate(bool persistToFile = true)
{
if (RootCertificate == null)
if (persistToFile && RootCertificate == null)
{
RootCertificate = LoadRootCertificate();
}
Expand All @@ -186,7 +189,7 @@ internal bool CreateTrustedRootCertificate()
exceptionFunc(e);
}

if (RootCertificate != null)
if (persistToFile && RootCertificate != null)
{
try
{
Expand All @@ -205,7 +208,7 @@ internal bool CreateTrustedRootCertificate()
/// <summary>
/// Trusts the root certificate.
/// </summary>
internal void TrustRootCertificate()
public void TrustRootCertificate()
{
//current user
TrustRootCertificate(StoreLocation.CurrentUser);
Expand All @@ -214,6 +217,18 @@ internal void TrustRootCertificate()
TrustRootCertificate(StoreLocation.LocalMachine);
}

/// <summary>
/// Removes the trusted certificates.
/// </summary>
public void RemoveTrustedRootCertificates()
{
//current user
RemoveTrustedRootCertificates(StoreLocation.CurrentUser);

//current system
RemoveTrustedRootCertificates(StoreLocation.LocalMachine);
}

/// <summary>
/// Create an SSL certificate
/// </summary>
Expand Down Expand Up @@ -336,6 +351,46 @@ internal void TrustRootCertificate(StoreLocation storeLocation)
}
}

/// <summary>
/// Remove the Root Certificate trust
/// </summary>
/// <param name="storeLocation"></param>
/// <returns></returns>
internal void RemoveTrustedRootCertificates(StoreLocation storeLocation)
{
if (RootCertificate == null)
{
exceptionFunc(
new Exception("Could not set root certificate"
+ " as system proxy since it is null or empty."));

return;
}

X509Store x509RootStore = new X509Store(StoreName.Root, storeLocation);
var x509PersonalStore = new X509Store(StoreName.My, storeLocation);

try
{
x509RootStore.Open(OpenFlags.ReadWrite);
x509PersonalStore.Open(OpenFlags.ReadWrite);

x509RootStore.Remove(RootCertificate);
x509PersonalStore.Remove(RootCertificate);
}
catch (Exception e)
{
exceptionFunc(
new Exception("Failed to make system trust root certificate "
+ $" for {storeLocation} store location. You may need admin rights.", e));
}
finally
{
x509RootStore.Close();
x509PersonalStore.Close();
}
}

public void Dispose()
{
}
Expand Down
42 changes: 21 additions & 21 deletions Titanium.Web.Proxy/ProxyServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ public partial class ProxyServer : IDisposable
/// </summary>
private bool proxyRunning { get; set; }

/// <summary>
/// Manages certificates used by this proxy
/// </summary>
private CertificateManager certificateManager { get; set; }

/// <summary>
/// An default exception log func
/// </summary>
Expand Down Expand Up @@ -64,13 +59,18 @@ private FireFoxProxySettingsManager firefoxProxySettingsManager
/// </summary>
public int BufferSize { get; set; } = 8192;

/// <summary>
/// Manages certificates used by this proxy
/// </summary>
public CertificateManager CertificateManager { get; }

/// <summary>
/// The root certificate
/// </summary>
public X509Certificate2 RootCertificate
{
get { return certificateManager.RootCertificate; }
set { certificateManager.RootCertificate = value; }
get { return CertificateManager.RootCertificate; }
set { CertificateManager.RootCertificate = value; }
}

/// <summary>
Expand All @@ -79,8 +79,8 @@ public X509Certificate2 RootCertificate
/// </summary>
public string RootCertificateIssuerName
{
get { return certificateManager.Issuer; }
set { certificateManager.RootCertificateName = value; }
get { return CertificateManager.Issuer; }
set { CertificateManager.Issuer = value; }
}

/// <summary>
Expand All @@ -92,8 +92,8 @@ public string RootCertificateIssuerName
/// </summary>
public string RootCertificateName
{
get { return certificateManager.RootCertificateName; }
set { certificateManager.Issuer = value; }
get { return CertificateManager.RootCertificateName; }
set { CertificateManager.RootCertificateName = value; }
}

/// <summary>
Expand Down Expand Up @@ -121,8 +121,8 @@ public bool TrustRootCertificate
/// </summary>
public CertificateEngine CertificateEngine
{
get { return certificateManager.Engine; }
set { certificateManager.Engine = value; }
get { return CertificateManager.Engine; }
set { CertificateManager.Engine = value; }
}

/// <summary>
Expand Down Expand Up @@ -251,7 +251,7 @@ public ProxyServer(string rootCertificateName, string rootCertificateIssuerName)
new FireFoxProxySettingsManager();
#endif

certificateManager = new CertificateManager(ExceptionFunc);
CertificateManager = new CertificateManager(ExceptionFunc);
if (rootCertificateName != null)
{
RootCertificateName = rootCertificateName;
Expand Down Expand Up @@ -356,7 +356,7 @@ public void SetAsSystemHttpsProxy(ExplicitProxyEndPoint endPoint)
EnsureRootCertificate();

//If certificate was trusted by the machine
if (certificateManager.CertValidated)
if (CertificateManager.CertValidated)
{
systemProxySettingsManager.SetHttpsProxy(
Equals(endPoint.IpAddress, IPAddress.Any) |
Expand Down Expand Up @@ -435,7 +435,7 @@ public void Start()
Listen(endPoint);
}

certificateManager.ClearIdleCertificates(CertificateCacheTimeOutMinutes);
CertificateManager.ClearIdleCertificates(CertificateCacheTimeOutMinutes);

proxyRunning = true;
}
Expand Down Expand Up @@ -468,7 +468,7 @@ public void Stop()

ProxyEndPoints.Clear();

certificateManager?.StopClearIdleCertificates();
CertificateManager?.StopClearIdleCertificates();

proxyRunning = false;
}
Expand All @@ -483,7 +483,7 @@ public void Dispose()
Stop();
}

certificateManager?.Dispose();
CertificateManager?.Dispose();
}

/// <summary>
Expand Down Expand Up @@ -543,13 +543,13 @@ private Task<ExternalProxy> GetSystemUpStreamProxy(SessionEventArgs sessionEvent

private void EnsureRootCertificate()
{
if (!certificateManager.CertValidated)
if (!CertificateManager.CertValidated)
{
certificateManager.CreateTrustedRootCertificate();
CertificateManager.CreateTrustedRootCertificate();

if (TrustRootCertificate)
{
certificateManager.TrustRootCertificate();
CertificateManager.TrustRootCertificate();
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions Titanium.Web.Proxy/RequestHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ private async Task HandleClient(ExplicitProxyEndPoint endPoint, TcpClient tcpCli
{
sslStream = new SslStream(clientStream, true);

var certificate = endPoint.GenericCertificate ?? certificateManager.CreateCertificate(httpRemoteUri.Host, false);
var certificate = endPoint.GenericCertificate ?? CertificateManager.CreateCertificate(httpRemoteUri.Host, false);

//Successfully managed to authenticate the client using the fake certificate
await sslStream.AuthenticateAsServerAsync(certificate, false,
Expand Down Expand Up @@ -177,7 +177,7 @@ private async Task HandleClient(TransparentProxyEndPoint endPoint, TcpClient tcp
var sslStream = new SslStream(clientStream, true);

//implement in future once SNI supported by SSL stream, for now use the same certificate
var certificate = certificateManager.CreateCertificate(endPoint.GenericCertificateName, false);
var certificate = CertificateManager.CreateCertificate(endPoint.GenericCertificateName, false);

try
{
Expand Down