Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.
Merged

Beta #238

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
@@ -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
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
15 changes: 8 additions & 7 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 Down Expand Up @@ -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,7 @@ public async Task Respond(Response response)
/// </summary>
public void Dispose()
{
WebSession.Dispose();
}
}
}
34 changes: 34 additions & 0 deletions Titanium.Web.Proxy/Extensions/FuncExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Threading.Tasks;

namespace Titanium.Web.Proxy.Extensions
{
internal static class FuncExtensions
{
public static void InvokeParallel<T>(this Func<object, T, Task> callback, object sender, T args)
{
Delegate[] invocationList = callback.GetInvocationList();
Task[] handlerTasks = new Task[invocationList.Length];

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

Task.WhenAll(handlerTasks).Wait();
}

public static async Task InvokeParallelAsync<T>(this Func<object, T, Task> callback, object sender, T args)
{
Delegate[] invocationList = callback.GetInvocationList();
Task[] handlerTasks = new Task[invocationList.Length];

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

await Task.WhenAll(handlerTasks);
}
}
}
Loading