diff --git a/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs b/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
index 6e1b67067..7a27bc17d 100644
--- a/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+++ b/Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
@@ -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;
@@ -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
diff --git a/Titanium.Web.Proxy/Network/CertificateManager.cs b/Titanium.Web.Proxy/Network/CertificateManager.cs
index 1d11444f2..d3e7547de 100644
--- a/Titanium.Web.Proxy/Network/CertificateManager.cs
+++ b/Titanium.Web.Proxy/Network/CertificateManager.cs
@@ -29,9 +29,9 @@ public enum CertificateEngine
///
/// A class to manage SSL certificates used by this proxy server
///
- internal class CertificateManager : IDisposable
+ public class CertificateManager : IDisposable
{
- public CertificateEngine Engine
+ internal CertificateEngine Engine
{
get { return engine; }
set
@@ -164,10 +164,13 @@ internal X509Certificate2 LoadRootCertificate()
///
/// Attempts to create a RootCertificate
///
- /// true if succeeded, else false
- internal bool CreateTrustedRootCertificate()
+ /// if set to true try to load/save the certificate from rootCert.pfx.
+ ///
+ /// true if succeeded, else false
+ ///
+ public bool CreateTrustedRootCertificate(bool persistToFile = true)
{
- if (RootCertificate == null)
+ if (persistToFile && RootCertificate == null)
{
RootCertificate = LoadRootCertificate();
}
@@ -186,7 +189,7 @@ internal bool CreateTrustedRootCertificate()
exceptionFunc(e);
}
- if (RootCertificate != null)
+ if (persistToFile && RootCertificate != null)
{
try
{
@@ -205,7 +208,7 @@ internal bool CreateTrustedRootCertificate()
///
/// Trusts the root certificate.
///
- internal void TrustRootCertificate()
+ public void TrustRootCertificate()
{
//current user
TrustRootCertificate(StoreLocation.CurrentUser);
@@ -214,6 +217,18 @@ internal void TrustRootCertificate()
TrustRootCertificate(StoreLocation.LocalMachine);
}
+ ///
+ /// Removes the trusted certificates.
+ ///
+ public void RemoveTrustedRootCertificates()
+ {
+ //current user
+ RemoveTrustedRootCertificates(StoreLocation.CurrentUser);
+
+ //current system
+ RemoveTrustedRootCertificates(StoreLocation.LocalMachine);
+ }
+
///
/// Create an SSL certificate
///
@@ -336,6 +351,46 @@ internal void TrustRootCertificate(StoreLocation storeLocation)
}
}
+ ///
+ /// Remove the Root Certificate trust
+ ///
+ ///
+ ///
+ 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()
{
}
diff --git a/Titanium.Web.Proxy/ProxyServer.cs b/Titanium.Web.Proxy/ProxyServer.cs
index 75ee12fef..e0ce23bc3 100644
--- a/Titanium.Web.Proxy/ProxyServer.cs
+++ b/Titanium.Web.Proxy/ProxyServer.cs
@@ -24,11 +24,6 @@ public partial class ProxyServer : IDisposable
///
private bool proxyRunning { get; set; }
- ///
- /// Manages certificates used by this proxy
- ///
- private CertificateManager certificateManager { get; set; }
-
///
/// An default exception log func
///
@@ -64,13 +59,18 @@ private FireFoxProxySettingsManager firefoxProxySettingsManager
///
public int BufferSize { get; set; } = 8192;
+ ///
+ /// Manages certificates used by this proxy
+ ///
+ public CertificateManager CertificateManager { get; }
+
///
/// The root certificate
///
public X509Certificate2 RootCertificate
{
- get { return certificateManager.RootCertificate; }
- set { certificateManager.RootCertificate = value; }
+ get { return CertificateManager.RootCertificate; }
+ set { CertificateManager.RootCertificate = value; }
}
///
@@ -79,8 +79,8 @@ public X509Certificate2 RootCertificate
///
public string RootCertificateIssuerName
{
- get { return certificateManager.Issuer; }
- set { certificateManager.RootCertificateName = value; }
+ get { return CertificateManager.Issuer; }
+ set { CertificateManager.Issuer = value; }
}
///
@@ -92,8 +92,8 @@ public string RootCertificateIssuerName
///
public string RootCertificateName
{
- get { return certificateManager.RootCertificateName; }
- set { certificateManager.Issuer = value; }
+ get { return CertificateManager.RootCertificateName; }
+ set { CertificateManager.RootCertificateName = value; }
}
///
@@ -121,8 +121,8 @@ public bool TrustRootCertificate
///
public CertificateEngine CertificateEngine
{
- get { return certificateManager.Engine; }
- set { certificateManager.Engine = value; }
+ get { return CertificateManager.Engine; }
+ set { CertificateManager.Engine = value; }
}
///
@@ -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;
@@ -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) |
@@ -435,7 +435,7 @@ public void Start()
Listen(endPoint);
}
- certificateManager.ClearIdleCertificates(CertificateCacheTimeOutMinutes);
+ CertificateManager.ClearIdleCertificates(CertificateCacheTimeOutMinutes);
proxyRunning = true;
}
@@ -468,7 +468,7 @@ public void Stop()
ProxyEndPoints.Clear();
- certificateManager?.StopClearIdleCertificates();
+ CertificateManager?.StopClearIdleCertificates();
proxyRunning = false;
}
@@ -483,7 +483,7 @@ public void Dispose()
Stop();
}
- certificateManager?.Dispose();
+ CertificateManager?.Dispose();
}
///
@@ -543,13 +543,13 @@ private Task GetSystemUpStreamProxy(SessionEventArgs sessionEvent
private void EnsureRootCertificate()
{
- if (!certificateManager.CertValidated)
+ if (!CertificateManager.CertValidated)
{
- certificateManager.CreateTrustedRootCertificate();
+ CertificateManager.CreateTrustedRootCertificate();
if (TrustRootCertificate)
{
- certificateManager.TrustRootCertificate();
+ CertificateManager.TrustRootCertificate();
}
}
}
diff --git a/Titanium.Web.Proxy/RequestHandler.cs b/Titanium.Web.Proxy/RequestHandler.cs
index b4fc6fa0c..37e41d8e6 100644
--- a/Titanium.Web.Proxy/RequestHandler.cs
+++ b/Titanium.Web.Proxy/RequestHandler.cs
@@ -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,
@@ -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
{