Commit 4047a006 authored by Jehonathan Thomas's avatar Jehonathan Thomas Committed by GitHub

Merge pull request #224 from honfika/develop

RootCertificate creation improvements
parents b6d18a61 d6a2f049
......@@ -17,6 +17,12 @@ namespace Titanium.Web.Proxy.Examples.Basic
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 @@ namespace Titanium.Web.Proxy.Examples.Basic
proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;
proxyServer.Stop();
//remove the generated certificates
//proxyServer.CertificateManager.RemoveTrustedRootCertificates();
}
//intecept & cancel redirect or update requests
......
......@@ -29,9 +29,9 @@ namespace Titanium.Web.Proxy.Network
/// <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
......@@ -164,10 +164,13 @@ namespace Titanium.Web.Proxy.Network
/// <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();
}
......@@ -186,7 +189,7 @@ namespace Titanium.Web.Proxy.Network
exceptionFunc(e);
}
if (RootCertificate != null)
if (persistToFile && RootCertificate != null)
{
try
{
......@@ -205,7 +208,7 @@ namespace Titanium.Web.Proxy.Network
/// <summary>
/// Trusts the root certificate.
/// </summary>
internal void TrustRootCertificate()
public void TrustRootCertificate()
{
//current user
TrustRootCertificate(StoreLocation.CurrentUser);
......@@ -214,6 +217,18 @@ namespace Titanium.Web.Proxy.Network
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>
......@@ -336,6 +351,46 @@ namespace Titanium.Web.Proxy.Network
}
}
/// <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()
{
}
......
......@@ -24,11 +24,6 @@ namespace Titanium.Web.Proxy
/// </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>
......@@ -64,13 +59,18 @@ namespace Titanium.Web.Proxy
/// </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>
......@@ -79,8 +79,8 @@ namespace Titanium.Web.Proxy
/// </summary>
public string RootCertificateIssuerName
{
get { return certificateManager.Issuer; }
set { certificateManager.RootCertificateName = value; }
get { return CertificateManager.Issuer; }
set { CertificateManager.Issuer = value; }
}
/// <summary>
......@@ -92,8 +92,8 @@ namespace Titanium.Web.Proxy
/// </summary>
public string RootCertificateName
{
get { return certificateManager.RootCertificateName; }
set { certificateManager.Issuer = value; }
get { return CertificateManager.RootCertificateName; }
set { CertificateManager.RootCertificateName = value; }
}
/// <summary>
......@@ -121,8 +121,8 @@ namespace Titanium.Web.Proxy
/// </summary>
public CertificateEngine CertificateEngine
{
get { return certificateManager.Engine; }
set { certificateManager.Engine = value; }
get { return CertificateManager.Engine; }
set { CertificateManager.Engine = value; }
}
/// <summary>
......@@ -251,7 +251,7 @@ namespace Titanium.Web.Proxy
new FireFoxProxySettingsManager();
#endif
certificateManager = new CertificateManager(ExceptionFunc);
CertificateManager = new CertificateManager(ExceptionFunc);
if (rootCertificateName != null)
{
RootCertificateName = rootCertificateName;
......@@ -356,7 +356,7 @@ namespace Titanium.Web.Proxy
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 @@ namespace Titanium.Web.Proxy
Listen(endPoint);
}
certificateManager.ClearIdleCertificates(CertificateCacheTimeOutMinutes);
CertificateManager.ClearIdleCertificates(CertificateCacheTimeOutMinutes);
proxyRunning = true;
}
......@@ -468,7 +468,7 @@ namespace Titanium.Web.Proxy
ProxyEndPoints.Clear();
certificateManager?.StopClearIdleCertificates();
CertificateManager?.StopClearIdleCertificates();
proxyRunning = false;
}
......@@ -483,7 +483,7 @@ namespace Titanium.Web.Proxy
Stop();
}
certificateManager?.Dispose();
CertificateManager?.Dispose();
}
/// <summary>
......@@ -543,13 +543,13 @@ namespace Titanium.Web.Proxy
private void EnsureRootCertificate()
{
if (!certificateManager.CertValidated)
if (!CertificateManager.CertValidated)
{
certificateManager.CreateTrustedRootCertificate();
CertificateManager.CreateTrustedRootCertificate();
if (TrustRootCertificate)
{
certificateManager.TrustRootCertificate();
CertificateManager.TrustRootCertificate();
}
}
}
......
......@@ -110,7 +110,7 @@ namespace Titanium.Web.Proxy
{
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 @@ namespace Titanium.Web.Proxy
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
{
......
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