Unverified Commit 741d1d8e authored by justcoding121's avatar justcoding121 Committed by GitHub

Merge pull request #422 from justcoding121/beta

Stable
parents 49dd522b 698084c6
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Titanium.Web.Proxy.Network; using Titanium.Web.Proxy.Network;
...@@ -12,7 +14,6 @@ namespace Titanium.Web.Proxy.UnitTests ...@@ -12,7 +14,6 @@ namespace Titanium.Web.Proxy.UnitTests
private static readonly string[] hostNames private static readonly string[] hostNames
= { "facebook.com", "youtube.com", "google.com", "bing.com", "yahoo.com" }; = { "facebook.com", "youtube.com", "google.com", "bing.com", "yahoo.com" };
private readonly Random random = new Random();
[TestMethod] [TestMethod]
public async Task Simple_BC_Create_Certificate_Test() public async Task Simple_BC_Create_Certificate_Test()
...@@ -21,22 +22,21 @@ namespace Titanium.Web.Proxy.UnitTests ...@@ -21,22 +22,21 @@ namespace Titanium.Web.Proxy.UnitTests
var mgr = new CertificateManager(null, null, false, false, false, new Lazy<ExceptionHandler>(() => (e => var mgr = new CertificateManager(null, null, false, false, false, new Lazy<ExceptionHandler>(() => (e =>
{ {
//Console.WriteLine(e.ToString() + e.InnerException != null ? e.InnerException.ToString() : string.Empty); Debug.WriteLine(e.ToString());
})).Value); Debug.WriteLine(e.InnerException?.ToString());
})).Value)
mgr.CertificateEngine = CertificateEngine.BouncyCastle; {
CertificateEngine = CertificateEngine.BouncyCastle
};
mgr.ClearIdleCertificates(); mgr.ClearIdleCertificates();
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
foreach (string host in hostNames) tasks.AddRange(hostNames.Select(host => Task.Run(() =>
{ {
tasks.Add(Task.Run(() => //get the connection
{ var certificate = mgr.CreateCertificate(host, false);
//get the connection Assert.IsNotNull(certificate);
var certificate = mgr.CreateCertificate(host, false); })));
Assert.IsNotNull(certificate);
}));
}
} }
await Task.WhenAll(tasks.ToArray()); await Task.WhenAll(tasks.ToArray());
...@@ -48,34 +48,34 @@ namespace Titanium.Web.Proxy.UnitTests ...@@ -48,34 +48,34 @@ namespace Titanium.Web.Proxy.UnitTests
[TestMethod] [TestMethod]
public async Task Simple_Create_Win_Certificate_Test() public async Task Simple_Create_Win_Certificate_Test()
{ {
var tasks = new List<Task>(); var tasks = new List<Task>();
var mgr = new CertificateManager(null, null, false, false, false, new Lazy<ExceptionHandler>(() => (e => var mgr = new CertificateManager(null, null, false, false, false, new Lazy<ExceptionHandler>(() => (e =>
{ {
//Console.WriteLine(e.ToString() + e.InnerException != null ? e.InnerException.ToString() : string.Empty); Debug.WriteLine(e.ToString());
})).Value); Debug.WriteLine(e.InnerException?.ToString());
})).Value)
{ CertificateEngine = CertificateEngine.DefaultWindows };
mgr.CertificateEngine = CertificateEngine.DefaultWindows; mgr.CreateRootCertificate();
mgr.CreateRootCertificate(true);
mgr.TrustRootCertificate(true); mgr.TrustRootCertificate(true);
mgr.ClearIdleCertificates(); mgr.ClearIdleCertificates();
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
foreach (string host in hostNames) tasks.AddRange(hostNames.Select(host => Task.Run(() =>
{ {
tasks.Add(Task.Run(() => //get the connection
{ var certificate = mgr.CreateCertificate(host, false);
//get the connection Assert.IsNotNull(certificate);
var certificate = mgr.CreateCertificate(host, false); })));
Assert.IsNotNull(certificate);
}));
}
} }
await Task.WhenAll(tasks.ToArray()); await Task.WhenAll(tasks.ToArray());
mgr.RemoveTrustedRootCertificate(true); mgr.RemoveTrustedRootCertificate(true);
mgr.StopClearIdleCertificates(); mgr.StopClearIdleCertificates();
} }
} }
} }
...@@ -2,9 +2,11 @@ ...@@ -2,9 +2,11 @@
using System.Reflection; using System.Reflection;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
namespace Titanium.Web.Proxy.Network.Certificate namespace Titanium.Web.Proxy.Network.Certificate
{ {
/// <inheritdoc />
/// <summary> /// <summary>
/// Certificate Maker - uses MakeCert /// Certificate Maker - uses MakeCert
/// Calls COM objects using reflection /// Calls COM objects using reflection
...@@ -104,8 +106,8 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -104,8 +106,8 @@ namespace Titanium.Web.Proxy.Network.Certificate
} }
typeX500DN.InvokeMember("Encode", BindingFlags.InvokeMethod, null, x500RootCertDN, typeValue); typeX500DN.InvokeMember("Encode", BindingFlags.InvokeMethod, null, x500RootCertDN, typeValue);
object sharedPrivateKey = null;
object sharedPrivateKey = null;
if (!isRoot) if (!isRoot)
{ {
sharedPrivateKey = this.sharedPrivateKey; sharedPrivateKey = this.sharedPrivateKey;
...@@ -276,49 +278,27 @@ namespace Titanium.Web.Proxy.Network.Certificate ...@@ -276,49 +278,27 @@ namespace Titanium.Web.Proxy.Network.Certificate
bool switchToMTAIfNeeded, X509Certificate2 signingCert = null, bool switchToMTAIfNeeded, X509Certificate2 signingCert = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
X509Certificate2 certificate = null;
if (switchToMTAIfNeeded && Thread.CurrentThread.GetApartmentState() != ApartmentState.MTA) if (switchToMTAIfNeeded && Thread.CurrentThread.GetApartmentState() != ApartmentState.MTA)
{ {
using (var manualResetEvent = new ManualResetEventSlim(false)) return Task.Run(() => MakeCertificateInternal(sSubjectCN, isRoot, false, signingCert),
{ cancellationToken).Result;
ThreadPool.QueueUserWorkItem(o =>
{
try
{
certificate = MakeCertificateInternal(sSubjectCN, isRoot, false, signingCert);
}
catch (Exception ex)
{
exceptionFunc(new Exception("Failed to create Win certificate", ex));
}
if (!cancellationToken.IsCancellationRequested)
{
manualResetEvent.Set();
}
});
manualResetEvent.Wait(TimeSpan.FromMinutes(1), cancellationToken);
}
return certificate;
} }
//Subject //Subject
string fullSubject = $"CN={sSubjectCN}"; string fullSubject = $"CN={sSubjectCN}";
//Sig Algo //Sig Algo
string HashAlgo = "SHA256"; const string hashAlgo = "SHA256";
//Grace Days //Grace Days
int GraceDays = -366; const int graceDays = -366;
//ValiDays //ValiDays
int ValidDays = 1825; const int validDays = 1825;
//KeyLength //KeyLength
int keyLength = 2048; const int keyLength = 2048;
var graceTime = DateTime.Now.AddDays(GraceDays); var graceTime = DateTime.Now.AddDays(graceDays);
var now = DateTime.Now; var now = DateTime.Now;
certificate = MakeCertificate(isRoot, sSubjectCN, fullSubject, keyLength, HashAlgo, graceTime, var certificate = MakeCertificate(isRoot, sSubjectCN, fullSubject, keyLength, hashAlgo, graceTime,
now.AddDays(ValidDays), isRoot ? null : signingCert); now.AddDays(validDays), isRoot ? null : signingCert);
return certificate; return certificate;
} }
} }
......
...@@ -79,11 +79,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -79,11 +79,7 @@ namespace Titanium.Web.Proxy.Network
{ {
this.exceptionFunc = exceptionFunc; this.exceptionFunc = exceptionFunc;
UserTrustRoot = userTrustRootCertificate; UserTrustRoot = userTrustRootCertificate || machineTrustRootCertificate;
if (machineTrustRootCertificate)
{
userTrustRootCertificate = true;
}
MachineTrustRoot = machineTrustRootCertificate; MachineTrustRoot = machineTrustRootCertificate;
TrustRootAsAdministrator = trustRootCertificateAsAdmin; TrustRootAsAdministrator = trustRootCertificateAsAdmin;
...@@ -338,14 +334,14 @@ namespace Titanium.Web.Proxy.Network ...@@ -338,14 +334,14 @@ namespace Titanium.Web.Proxy.Network
return; return;
} }
var x509store = new X509Store(storeName, storeLocation); var x509Store = new X509Store(storeName, storeLocation);
//TODO //TODO
//also it should do not duplicate if certificate already exists //also it should do not duplicate if certificate already exists
try try
{ {
x509store.Open(OpenFlags.ReadWrite); x509Store.Open(OpenFlags.ReadWrite);
x509store.Add(RootCertificate); x509Store.Add(RootCertificate);
} }
catch (Exception e) catch (Exception e)
{ {
...@@ -356,7 +352,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -356,7 +352,7 @@ namespace Titanium.Web.Proxy.Network
} }
finally finally
{ {
x509store.Close(); x509Store.Close();
} }
} }
...@@ -436,7 +432,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -436,7 +432,7 @@ namespace Titanium.Web.Proxy.Network
if (!File.Exists(certificatePath)) if (!File.Exists(certificatePath))
{ {
certificate = MakeCertificate(certificateName, isRootCertificate); certificate = MakeCertificate(certificateName, false);
//store as cache //store as cache
Task.Run(() => Task.Run(() =>
...@@ -460,7 +456,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -460,7 +456,7 @@ namespace Titanium.Web.Proxy.Network
//if load failed create again //if load failed create again
catch catch
{ {
certificate = MakeCertificate(certificateName, isRootCertificate); certificate = MakeCertificate(certificateName, false);
} }
} }
} }
...@@ -485,8 +481,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -485,8 +481,7 @@ namespace Titanium.Web.Proxy.Network
internal async Task<X509Certificate2> CreateCertificateAsync(string certificateName) internal async Task<X509Certificate2> CreateCertificateAsync(string certificateName)
{ {
//check in cache first //check in cache first
CachedCertificate cached; if (certificateCache.TryGetValue(certificateName, out var cached))
if (certificateCache.TryGetValue(certificateName, out cached))
{ {
cached.LastAccess = DateTime.Now; cached.LastAccess = DateTime.Now;
return cached.Certificate; return cached.Certificate;
...@@ -494,8 +489,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -494,8 +489,7 @@ namespace Titanium.Web.Proxy.Network
//handle burst requests with same certificate name //handle burst requests with same certificate name
//by checking for existing task for same certificate name //by checking for existing task for same certificate name
Task<X509Certificate2> task; if (pendingCertificateCreationTasks.TryGetValue(certificateName, out var task))
if (pendingCertificateCreationTasks.TryGetValue(certificateName, out task))
{ {
return await task; return await task;
} }
...@@ -785,12 +779,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -785,12 +779,7 @@ namespace Titanium.Web.Proxy.Network
public void EnsureRootCertificate(bool userTrustRootCertificate, public void EnsureRootCertificate(bool userTrustRootCertificate,
bool machineTrustRootCertificate, bool trustRootCertificateAsAdmin = false) bool machineTrustRootCertificate, bool trustRootCertificateAsAdmin = false)
{ {
UserTrustRoot = userTrustRootCertificate; UserTrustRoot = userTrustRootCertificate || machineTrustRootCertificate;
if (machineTrustRootCertificate)
{
userTrustRootCertificate = true;
}
MachineTrustRoot = machineTrustRootCertificate; MachineTrustRoot = machineTrustRootCertificate;
TrustRootAsAdministrator = trustRootCertificateAsAdmin; TrustRootAsAdministrator = trustRootCertificateAsAdmin;
...@@ -909,7 +898,7 @@ namespace Titanium.Web.Proxy.Network ...@@ -909,7 +898,7 @@ namespace Titanium.Web.Proxy.Network
success = false; success = false;
} }
process.WaitForExit(); process?.WaitForExit();
} }
} }
catch catch
......
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