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
Show all changes
54 commits
Select commit Hold shift + click to select a range
72c9135
Allow to generate root certificate with Titanium without storing it i…
honfika May 15, 2017
0cb7db7
Allow to remove the root certificates from windows certmgr
honfika May 15, 2017
f6277d3
Certificate Issuer/Name setter fix
honfika May 15, 2017
1178e5d
Merge pull request #224 from honfika/develop
justcoding121 May 15, 2017
985890a
#184 add connection count; TODO: Find out why large number of client …
May 15, 2017
922398f
#184 move linger state experimentally to avoid object disposed except…
May 15, 2017
45b0d87
Add Server Connection Count; Reduce Params
May 15, 2017
eed3ff9
print server connections for debugging
May 15, 2017
ac58fee
decrement server connection when closed
May 15, 2017
90c935e
- Create less TcpRow objects
honfika May 15, 2017
5e9e129
Fix for #227
honfika May 15, 2017
77cc1a7
Merge pull request #228 from honfika/develop
justcoding121 May 15, 2017
d5082b4
Fix server connection reuse
justcoding121 May 15, 2017
07f86b8
format
justcoding121 May 15, 2017
063d78a
call dispose correctly
justcoding121 May 15, 2017
f183d65
update sample proj for convenience (don't block google, evade dropbox)
May 15, 2017
7b84816
reuse buffers, missing dispose added
honfika May 15, 2017
278e2a5
reduce timeout; cleanup
justcoding121 May 15, 2017
11a2221
Merge pull request #230 from justcoding121/develop
justcoding121 May 15, 2017
f089acc
ServerConnection?.Dispose(); Call removed.
honfika May 15, 2017
dff9ef7
Merge pull request #229 from honfika/develop
justcoding121 May 16, 2017
e6d8eb2
connection count locking + usings sorted
honfika May 16, 2017
a7d679d
event parallel invoke moved to extension class
honfika May 16, 2017
c44631d
cleanup
honfika May 16, 2017
0f6434e
Pass the ProxyServer object to CertificateSelection callbacks
honfika May 16, 2017
585ec8e
Merge pull request #233 from honfika/develop
justcoding121 May 16, 2017
e7c1c98
#231 Fix server count; don't dispose twice
May 16, 2017
fde5838
revert experimental changes
May 16, 2017
270cb13
Space within single line array initializer
honfika May 16, 2017
1641a29
#232 experimental fix
May 16, 2017
94afaa0
Merge pull request #236 from honfika/develop
justcoding121 May 16, 2017
20ce85b
set body bytes to null after use
May 16, 2017
30f5389
move Dispose all to finally blocks
honfika May 16, 2017
c994c82
fix issue with console quickedit mode where app hangs until key press
May 16, 2017
ab64887
improve readability
May 16, 2017
acde2df
dispose flag changed to disposed flag in HandleHttpSessionRequestInte…
honfika May 16, 2017
f9ca3b0
Merge pull request #237 from honfika/develop
justcoding121 May 16, 2017
1c35a2d
#184 dispose args
May 16, 2017
522d0b5
disable quick edit causing app hang
May 16, 2017
b8355cd
Merge pull request #238 from justcoding121/develop
justcoding121 May 16, 2017
652b444
move around methods based on logical flow
justcoding121 May 16, 2017
f1e3741
Allow to query the root certificate status (IsRootCertificateTrusted …
honfika May 17, 2017
cad1b6d
Not sure why this was added in PR #187
May 17, 2017
03e69d2
Enterprise parameter removed
honfika May 17, 2017
78746e8
Merge pull request #239 from honfika/develop
justcoding121 May 17, 2017
10e5e31
move dispose; remove references to actice objects after dispose
May 17, 2017
7fa3a9b
Merge pull request #240 from justcoding121/develop
justcoding121 May 18, 2017
a630f28
add TLS cert revocation check flag; cleanup
justcoding121 May 19, 2017
cccc61a
Merge pull request #241 from justcoding121/develop
justcoding121 May 19, 2017
c046a32
already supported
justcoding121 May 19, 2017
2260a89
#242 Fix external proxy
May 19, 2017
3b4b6ad
Merge branch 'develop' of https://github.com/justcoding121/Titanium-W…
May 19, 2017
75fb00c
Merge pull request #243 from justcoding121/develop
justcoding121 May 19, 2017
42313cb
Merge branch 'stable' of https://github.com/justcoding121/Titanium-We…
May 19, 2017
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
@@ -0,0 +1,52 @@
using System;
using System.Runtime.InteropServices;

namespace Titanium.Web.Proxy.Examples.Basic.Helpers
{
/// <summary>
/// Adapated from
/// http://stackoverflow.com/questions/13656846/how-to-programmatic-disable-c-sharp-console-applications-quick-edit-mode
/// </summary>
internal static class ConsoleHelper
{
const uint ENABLE_QUICK_EDIT = 0x0040;

// STD_INPUT_HANDLE (DWORD): -10 is the standard input device.
const int STD_INPUT_HANDLE = -10;

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);

[DllImport("kernel32.dll")]
static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);

[DllImport("kernel32.dll")]
static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);

internal static bool DisableQuickEditMode()
{

IntPtr consoleHandle = GetStdHandle(STD_INPUT_HANDLE);

// get current console mode
uint consoleMode;
if (!GetConsoleMode(consoleHandle, out consoleMode))
{
// ERROR: Unable to get console mode.
return false;
}

// Clear the quick edit bit in the mode flags
consoleMode &= ~ENABLE_QUICK_EDIT;

// set the new mode
if (!SetConsoleMode(consoleHandle, consoleMode))
{
// ERROR: Unable to set console mode
return false;
}

return true;
}
}
}
10 changes: 8 additions & 2 deletions Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Titanium.Web.Proxy.Examples.Basic.Helpers;

namespace Titanium.Web.Proxy.Examples.Basic
{
Expand All @@ -9,11 +11,13 @@ public class Program

public static void Main(string[] args)
{
//fix console hang due to QuickEdit mode
ConsoleHelper.DisableQuickEditMode();

//On Console exit make sure we also exit the proxy
NativeMethods.Handler = ConsoleEventCallback;
NativeMethods.SetConsoleCtrlHandler(NativeMethods.Handler, true);


//Start proxy controller
controller.StartProxy();

Expand Down Expand Up @@ -50,5 +54,7 @@ internal static class NativeMethods

// Pinvoke
internal delegate bool ConsoleEventDelegate(int eventType);

}
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models;
Expand Down Expand Up @@ -47,18 +47,18 @@ public void StartProxy()
//Exclude Https addresses you don't want to proxy
//Useful for clients that use certificate pinning
//for example google.com and dropbox.com
ExcludedHttpsHostNameRegex = new List<string>() { "dropbox.com" }
ExcludedHttpsHostNameRegex = new List<string> { "dropbox.com" }

//Include Https addresses you want to proxy (others will be excluded)
//for example github.com
// IncludedHttpsHostNameRegex = new List<string>() { "github.com" }
//IncludedHttpsHostNameRegex = new List<string> { "github.com" }

//You can set only one of the ExcludedHttpsHostNameRegex and IncludedHttpsHostNameRegex properties, otherwise ArgumentException will be thrown

//Use self-issued generic certificate on all https requests
//Optimizes performance by not creating a certificate for each https-enabled domain
//Useful when certificate trust is not required by proxy clients
// GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
//GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
};

//An explicit endpoint is where the client knows about the existence of a proxy
Expand Down Expand Up @@ -107,7 +107,7 @@ public void Stop()
//intecept & cancel redirect or update requests
public async Task OnRequest(object sender, SessionEventArgs e)
{
Console.WriteLine("Active Client Connections:" + ((ProxyServer) sender).ClientConnectionCount);
Console.WriteLine("Active Client Connections:" + ((ProxyServer)sender).ClientConnectionCount);
Console.WriteLine(e.WebSession.Request.Url);

//read request headers
Expand Down Expand Up @@ -150,7 +150,7 @@ public async Task OnRequest(object sender, SessionEventArgs e)
//Modify response
public async Task OnResponse(object sender, SessionEventArgs e)
{
Console.WriteLine("Active Server Connections:" + (sender as ProxyServer).ServerConnectionCount);
Console.WriteLine("Active Server Connections:" + ((ProxyServer)sender).ServerConnectionCount);

if (requestBodyHistory.ContainsKey(e.Id))
{
Expand Down Expand Up @@ -189,7 +189,7 @@ public async Task OnResponse(object sender, SessionEventArgs e)
public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{
//set IsValid to true/false based on Certificate Errors
if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
if (e.SslPolicyErrors == SslPolicyErrors.None)
{
e.IsValid = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Helpers\ConsoleHelper.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ProxyTestController.cs" />
Expand Down
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ Features
* Safely relays Web Socket requests over HTTP
* Support mutual SSL authentication
* Fully asynchronous proxy
* Supports proxy authentication

* Supports proxy authentication & automatic proxy detection

Usage
=====
Expand Down Expand Up @@ -204,10 +203,8 @@ public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs
```
Future road map (Pull requests are welcome!)
============
* Implement Kerberos/NTLM authentication over HTTP protocols for windows domain
* Support Server Name Indication (SNI) for transparent endpoints
* Support HTTP 2.0
* Support upstream AutoProxy detection
* Support SOCKS protocol
* Implement Kerberos/NTLM authentication over HTTP protocols for windows domain


Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
Expand Down
10 changes: 5 additions & 5 deletions Tests/Titanium.Web.Proxy.IntegrationTests/SslTests.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Net.Security;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Models;
using System.Net.Http;
using System.Diagnostics;

namespace Titanium.Web.Proxy.IntegrationTests
{
[TestClass]
public class SslTests
{
[TestMethod]

public void TestSsl()
{
//expand this to stress test to find
Expand Down Expand Up @@ -103,7 +103,7 @@ public async Task OnResponse(object sender, SessionEventArgs e)
public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{
//set IsValid to true/false based on Certificate Errors
if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
if (e.SslPolicyErrors == SslPolicyErrors.None)
{
e.IsValid = true;
}
Expand Down
10 changes: 3 additions & 7 deletions Tests/Titanium.Web.Proxy.UnitTests/CertificateManagerTests.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Titanium.Web.Proxy.Network;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace Titanium.Web.Proxy.UnitTests
{
[TestClass]
public class CertificateManagerTests
{
private static readonly string[] hostNames
= new string[] { "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();

Expand All @@ -36,16 +35,13 @@ public async Task Simple_Create_Certificate_Stress_Test()
var certificate = mgr.CreateCertificate(host, false);

Assert.IsNotNull(certificate);

}));

}
}

await Task.WhenAll(tasks.ToArray());

mgr.StopClearIdleCertificates();

}
}
}
15 changes: 14 additions & 1 deletion Titanium.Web.Proxy.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
<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:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/LINE_FEED_AT_FILE_END/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_AFTER_TYPECAST_PARENTHESES/@EntryValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SPACE_WITHIN_SINGLE_LINE_ARRAY_INITIALIZER_BRACES/@EntryValue">True</s:Boolean>
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">240</s:Int64>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=BC/@EntryIndexedValue">BC</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CN/@EntryIndexedValue">CN</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DN/@EntryIndexedValue">DN</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EKU/@EntryIndexedValue">EKU</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=KU/@EntryIndexedValue">KU</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MTA/@EntryIndexedValue">MTA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OID/@EntryIndexedValue">OID</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OIDS/@EntryIndexedValue">OIDS</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/=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/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>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
28 changes: 5 additions & 23 deletions Titanium.Web.Proxy/CertificateHandler.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using System;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Extensions;

namespace Titanium.Web.Proxy
{
Expand Down Expand Up @@ -32,17 +32,8 @@ internal bool ValidateServerCertificate(
SslPolicyErrors = sslPolicyErrors
};


Delegate[] invocationList = ServerCertificateValidationCallback.GetInvocationList();
Task[] handlerTasks = new Task[invocationList.Length];

for (int i = 0; i < invocationList.Length; i++)
{
handlerTasks[i] = ((Func<object, CertificateValidationEventArgs, Task>) invocationList[i])(null, args);
}

Task.WhenAll(handlerTasks).Wait();

//why is the sender null?
ServerCertificateValidationCallback.InvokeParallel(this, args);
return args.IsValid;
}

Expand Down Expand Up @@ -108,17 +99,8 @@ internal X509Certificate SelectClientCertificate(
ClientCertificate = clientCertificate
};


Delegate[] invocationList = ClientCertificateSelectionCallback.GetInvocationList();
Task[] handlerTasks = new Task[invocationList.Length];

for (int i = 0; i < invocationList.Length; i++)
{
handlerTasks[i] = ((Func<object, CertificateSelectionEventArgs, Task>) invocationList[i])(null, args);
}

Task.WhenAll(handlerTasks).Wait();

//why is the sender null?
ClientCertificateSelectionCallback.InvokeParallel(this, args);
return args.ClientCertificate;
}

Expand Down
21 changes: 13 additions & 8 deletions Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using Titanium.Web.Proxy.Exceptions;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Decompression;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Http.Responses;
using Titanium.Web.Proxy.Extensions;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Network;
using System.Net;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network;

namespace Titanium.Web.Proxy.EventArguments
{
Expand All @@ -30,7 +30,7 @@ public class SessionEventArgs : EventArgs, IDisposable
/// <summary>
/// Holds a reference to proxy response handler method
/// </summary>
private readonly Func<SessionEventArgs, Task> httpResponseHandler;
private Func<SessionEventArgs, Task> httpResponseHandler;

/// <summary>
/// Holds a reference to client
Expand All @@ -56,7 +56,7 @@ public class SessionEventArgs : EventArgs, IDisposable
/// <summary>
/// Client End Point.
/// </summary>
public IPEndPoint ClientEndPoint => (IPEndPoint) ProxyClient.TcpClient.Client.RemoteEndPoint;
public IPEndPoint ClientEndPoint => (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint;

/// <summary>
/// A web session corresponding to a single request/response sequence
Expand Down Expand Up @@ -158,7 +158,7 @@ private async Task ReadResponseBody()
await WebSession.ServerConnection.StreamReader.CopyBytesToStream(bufferSize, responseBodyStream,
WebSession.Response.ContentLength);
}
else if ((WebSession.Response.HttpVersion.Major == 1 && WebSession.Response.HttpVersion.Minor == 0) || WebSession.Response.ContentLength == -1)
else if (WebSession.Response.HttpVersion.Major == 1 && WebSession.Response.HttpVersion.Minor == 0 || WebSession.Response.ContentLength == -1)
{
await WebSession.ServerConnection.StreamReader.CopyBytesToStream(bufferSize, responseBodyStream, long.MaxValue);
}
Expand Down Expand Up @@ -522,6 +522,11 @@ public async Task Respond(Response response)
/// </summary>
public void Dispose()
{
httpResponseHandler = null;
CustomUpStreamHttpProxyUsed = null;
CustomUpStreamHttpsProxyUsed = null;

WebSession.Dispose();
}
}
}
Loading