Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
T
Titanium-Web-Proxy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Titanium-Web-Proxy
Commits
70c107a4
Commit
70c107a4
authored
Jun 17, 2017
by
justcoding121
Committed by
justcoding121
Jun 17, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #276 from honfika/develop
Code cleanup - if you prefer any other style, please let me know
parents
6493ea87
126eed5e
Hide whitespace changes
Inline
Side-by-side
Showing
51 changed files
with
680 additions
and
766 deletions
+680
-766
ConsoleHelper.cs
...itanium.Web.Proxy.Examples.Basic/Helpers/ConsoleHelper.cs
+1
-2
Program.cs
Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs
+0
-2
ProxyTestController.cs
.../Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+7
-6
SslTests.cs
Tests/Titanium.Web.Proxy.IntegrationTests/SslTests.cs
+1
-1
CertificateManagerTests.cs
...s/Titanium.Web.Proxy.UnitTests/CertificateManagerTests.cs
+1
-1
SystemProxyTest.cs
Tests/Titanium.Web.Proxy.UnitTests/SystemProxyTest.cs
+0
-4
WinAuthTests.cs
Tests/Titanium.Web.Proxy.UnitTests/WinAuthTests.cs
+3
-3
Titanium.Web.Proxy.sln.DotSettings
Titanium.Web.Proxy.sln.DotSettings
+5
-1
CertificateHandler.cs
Titanium.Web.Proxy/CertificateHandler.cs
+6
-18
SessionEventArgs.cs
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
+12
-17
BodyNotFoundException.cs
Titanium.Web.Proxy/Exceptions/BodyNotFoundException.cs
+1
-2
FuncExtensions.cs
Titanium.Web.Proxy/Extensions/FuncExtensions.cs
+4
-4
HttpWebRequestExtensions.cs
Titanium.Web.Proxy/Extensions/HttpWebRequestExtensions.cs
+1
-2
HttpWebResponseExtensions.cs
Titanium.Web.Proxy/Extensions/HttpWebResponseExtensions.cs
+1
-2
StreamExtensions.cs
Titanium.Web.Proxy/Extensions/StreamExtensions.cs
+7
-6
TcpExtensions.cs
Titanium.Web.Proxy/Extensions/TcpExtensions.cs
+1
-1
BufferPool.cs
Titanium.Web.Proxy/Helpers/BufferPool.cs
+1
-6
CustomBinaryReader.cs
Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
+2
-2
CustomBufferedStream.cs
Titanium.Web.Proxy/Helpers/CustomBufferedStream.cs
+2
-3
Firefox.cs
Titanium.Web.Proxy/Helpers/Firefox.cs
+6
-7
HttpHelper.cs
Titanium.Web.Proxy/Helpers/HttpHelper.cs
+2
-3
Network.cs
Titanium.Web.Proxy/Helpers/Network.cs
+3
-3
ProxyInfo.cs
Titanium.Web.Proxy/Helpers/ProxyInfo.cs
+5
-5
RunTime.cs
Titanium.Web.Proxy/Helpers/RunTime.cs
+2
-3
SystemProxy.cs
Titanium.Web.Proxy/Helpers/SystemProxy.cs
+4
-10
Tcp.cs
Titanium.Web.Proxy/Helpers/Tcp.cs
+14
-20
NativeMethods.WinHttp.cs
Titanium.Web.Proxy/Helpers/WinHttp/NativeMethods.WinHttp.cs
+4
-3
WinHttpHandle.cs
Titanium.Web.Proxy/Helpers/WinHttp/WinHttpHandle.cs
+1
-1
WinHttpWebProxyFinder.cs
Titanium.Web.Proxy/Helpers/WinHttp/WinHttpWebProxyFinder.cs
+11
-11
HeaderParser.cs
Titanium.Web.Proxy/Http/HeaderParser.cs
+6
-3
HttpWebClient.cs
Titanium.Web.Proxy/Http/HttpWebClient.cs
+8
-7
Request.cs
Titanium.Web.Proxy/Http/Request.cs
+27
-25
Response.cs
Titanium.Web.Proxy/Http/Response.cs
+24
-21
EndPoint.cs
Titanium.Web.Proxy/Models/EndPoint.cs
+7
-6
BCCertificateMaker.cs
Titanium.Web.Proxy/Network/Certificate/BCCertificateMaker.cs
+10
-12
WinCertificateMaker.cs
...nium.Web.Proxy/Network/Certificate/WinCertificateMaker.cs
+6
-8
CertificateManager.cs
Titanium.Web.Proxy/Network/CertificateManager.cs
+18
-17
TcpConnectionFactory.cs
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
+14
-17
TcpTable.cs
Titanium.Web.Proxy/Network/Tcp/TcpTable.cs
+3
-5
Common.cs
Titanium.Web.Proxy/Network/WinAuth/Security/Common.cs
+53
-36
LittleEndian.cs
Titanium.Web.Proxy/Network/WinAuth/Security/LittleEndian.cs
+169
-174
Message.cs
Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs
+38
-55
State.cs
Titanium.Web.Proxy/Network/WinAuth/Security/State.cs
+9
-9
WinAuthEndPoint.cs
...ium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs
+56
-65
WinAuthHandler.cs
Titanium.Web.Proxy/Network/WinAuth/WinAuthHandler.cs
+7
-11
ProxyAuthorizationHandler.cs
Titanium.Web.Proxy/ProxyAuthorizationHandler.cs
+6
-5
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+11
-13
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+40
-46
ResponseHandler.cs
Titanium.Web.Proxy/ResponseHandler.cs
+20
-29
ProxyConstants.cs
Titanium.Web.Proxy/Shared/ProxyConstants.cs
+1
-2
WinAuthHandler.cs
Titanium.Web.Proxy/WinAuthHandler.cs
+39
-51
No files found.
Examples/Titanium.Web.Proxy.Examples.Basic/Helpers/ConsoleHelper.cs
View file @
70c107a4
...
...
@@ -25,8 +25,7 @@ namespace Titanium.Web.Proxy.Examples.Basic.Helpers
internal
static
bool
DisableQuickEditMode
()
{
IntPtr
consoleHandle
=
GetStdHandle
(
STD_INPUT_HANDLE
);
var
consoleHandle
=
GetStdHandle
(
STD_INPUT_HANDLE
);
// get current console mode
uint
consoleMode
;
...
...
Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs
View file @
70c107a4
using
System
;
using
System.Diagnostics
;
using
System.Runtime.InteropServices
;
using
Titanium.Web.Proxy.Examples.Basic.Helpers
;
namespace
Titanium.Web.Proxy.Examples.Basic
...
...
Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
View file @
70c107a4
using
System
;
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.Net
;
using
System.Net.Security
;
...
...
@@ -55,7 +54,10 @@ namespace Titanium.Web.Proxy.Examples.Basic
//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
...
...
@@ -91,8 +93,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
//proxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
foreach
(
var
endPoint
in
proxyServer
.
ProxyEndPoints
)
Console
.
WriteLine
(
"Listening on '{0}' endpoint at Ip {1} and port: {2} "
,
endPoint
.
GetType
().
Name
,
endPoint
.
IpAddress
,
endPoint
.
Port
);
Console
.
WriteLine
(
"Listening on '{0}' endpoint at Ip {1} and port: {2} "
,
endPoint
.
GetType
().
Name
,
endPoint
.
IpAddress
,
endPoint
.
Port
);
//Only explicit proxies can be set as system proxy!
//proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
...
...
@@ -125,7 +126,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
if
(
e
.
WebSession
.
Request
.
HasBody
)
{
//Get/Set request body bytes
byte
[]
bodyBytes
=
await
e
.
GetRequestBody
();
var
bodyBytes
=
await
e
.
GetRequestBody
();
await
e
.
SetRequestBody
(
bodyBytes
);
//Get/Set request body as string
...
...
@@ -179,7 +180,7 @@ namespace Titanium.Web.Proxy.Examples.Basic
{
if
(
e
.
WebSession
.
Response
.
ContentType
!=
null
&&
e
.
WebSession
.
Response
.
ContentType
.
Trim
().
ToLower
().
Contains
(
"text/html"
))
{
byte
[]
bodyBytes
=
await
e
.
GetResponseBody
();
var
bodyBytes
=
await
e
.
GetResponseBody
();
await
e
.
SetResponseBody
(
bodyBytes
);
string
body
=
await
e
.
GetResponseBodyAsString
();
...
...
Tests/Titanium.Web.Proxy.IntegrationTests/SslTests.cs
View file @
70c107a4
...
...
@@ -18,7 +18,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
{
//expand this to stress test to find
//why in long run proxy becomes unresponsive as per issue #184
var
testUrl
=
"https://google.com"
;
string
testUrl
=
"https://google.com"
;
int
proxyPort
=
8086
;
var
proxy
=
new
ProxyTestController
();
proxy
.
StartProxy
(
proxyPort
);
...
...
Tests/Titanium.Web.Proxy.UnitTests/CertificateManagerTests.cs
View file @
70c107a4
...
...
@@ -25,7 +25,7 @@ namespace Titanium.Web.Proxy.UnitTests
for
(
int
i
=
0
;
i
<
1000
;
i
++)
{
foreach
(
var
host
in
hostNames
)
foreach
(
string
host
in
hostNames
)
{
tasks
.
Add
(
Task
.
Run
(
async
()
=>
{
...
...
Tests/Titanium.Web.Proxy.UnitTests/SystemProxyTest.cs
View file @
70c107a4
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Net
;
using
System.Text
;
using
System.Threading.Tasks
;
using
Microsoft.VisualStudio.TestTools.UnitTesting
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Helpers.WinHttp
;
...
...
Tests/Titanium.Web.Proxy.UnitTests/WinAuthTests.cs
View file @
70c107a4
using
Microsoft.VisualStudio.TestTools.UnitTesting
;
using
System
;
using
System
;
using
Microsoft.VisualStudio.TestTools.UnitTesting
;
using
Titanium.Web.Proxy.Network.WinAuth
;
namespace
Titanium.Web.Proxy.UnitTests
...
...
@@ -10,7 +10,7 @@ namespace Titanium.Web.Proxy.UnitTests
[
TestMethod
]
public
void
Test_Acquire_Client_Token
()
{
var
token
=
WinAuthHandler
.
GetInitialAuthToken
(
"mylocalserver.com"
,
"NTLM"
,
Guid
.
NewGuid
());
string
token
=
WinAuthHandler
.
GetInitialAuthToken
(
"mylocalserver.com"
,
"NTLM"
,
Guid
.
NewGuid
());
Assert
.
IsTrue
(
token
.
Length
>
1
);
}
}
...
...
Titanium.Web.Proxy.sln.DotSettings
View file @
70c107a4
<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:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_CASE_STATEMENT_STYLE/@EntryValue">LINE_BREAK</s:String>
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/SIMPLE_EMBEDDED_STATEMENT_STYLE/@EntryValue">LINE_BREAK</s:String>
<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:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">160</s:Int64>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForBuiltInTypes/@EntryValue">UseExplicitType</s:String>
<s:String x:Key="/Default/CodeStyle/CSharpVarKeywordUsage/ForSimpleTypes/@EntryValue">UseVar</s:String>
<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>
...
...
Titanium.Web.Proxy/CertificateHandler.cs
View file @
70c107a4
...
...
@@ -16,11 +16,7 @@ namespace Titanium.Web.Proxy
/// <param name="chain"></param>
/// <param name="sslPolicyErrors"></param>
/// <returns></returns>
internal
bool
ValidateServerCertificate
(
object
sender
,
X509Certificate
certificate
,
X509Chain
chain
,
SslPolicyErrors
sslPolicyErrors
)
internal
bool
ValidateServerCertificate
(
object
sender
,
X509Certificate
certificate
,
X509Chain
chain
,
SslPolicyErrors
sslPolicyErrors
)
{
//if user callback is registered then do it
if
(
ServerCertificateValidationCallback
!=
null
)
...
...
@@ -56,22 +52,15 @@ namespace Titanium.Web.Proxy
/// <param name="remoteCertificate"></param>
/// <param name="acceptableIssuers"></param>
/// <returns></returns>
internal
X509Certificate
SelectClientCertificate
(
object
sender
,
string
targetHost
,
X509CertificateCollection
localCertificates
,
X509Certificate
remoteCertificate
,
string
[]
acceptableIssuers
)
internal
X509Certificate
SelectClientCertificate
(
object
sender
,
string
targetHost
,
X509CertificateCollection
localCertificates
,
X509Certificate
remoteCertificate
,
string
[]
acceptableIssuers
)
{
X509Certificate
clientCertificate
=
null
;
if
(
acceptableIssuers
!=
null
&&
acceptableIssuers
.
Length
>
0
&&
localCertificates
!=
null
&&
localCertificates
.
Count
>
0
)
if
(
acceptableIssuers
!=
null
&&
acceptableIssuers
.
Length
>
0
&&
localCertificates
!=
null
&&
localCertificates
.
Count
>
0
)
{
// Use the first certificate that is from an acceptable issuer.
foreach
(
X509Certificate
certificate
in
localCertificates
)
foreach
(
var
certificate
in
localCertificates
)
{
string
issuer
=
certificate
.
Issuer
;
if
(
Array
.
IndexOf
(
acceptableIssuers
,
issuer
)
!=
-
1
)
...
...
@@ -81,8 +70,7 @@ namespace Titanium.Web.Proxy
}
}
if
(
localCertificates
!=
null
&&
localCertificates
.
Count
>
0
)
if
(
localCertificates
!=
null
&&
localCertificates
.
Count
>
0
)
{
clientCertificate
=
localCertificates
[
0
];
}
...
...
Titanium.Web.Proxy/EventArguments/SessionEventArgs.cs
View file @
70c107a4
...
...
@@ -48,7 +48,6 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary>
public
Guid
Id
=>
WebSession
.
RequestId
;
/// <summary>
/// Should we send the request again
/// </summary>
...
...
@@ -59,8 +58,7 @@ namespace Titanium.Web.Proxy.EventArguments
{
if
(
WebSession
.
Response
.
ResponseStatusCode
==
null
)
{
throw
new
Exception
(
"Response status code is null. Cannot request again a request "
+
"which was never send to server."
);
throw
new
Exception
(
"Response status code is null. Cannot request again a request "
+
"which was never send to server."
);
}
reRequest
=
value
;
...
...
@@ -113,8 +111,7 @@ namespace Titanium.Web.Proxy.EventArguments
//GET request don't have a request body to read
if
(!
WebSession
.
Request
.
HasBody
)
{
throw
new
BodyNotFoundException
(
"Request don't have a body. "
+
"Please verify that this request is a Http POST/PUT/PATCH and request "
+
throw
new
BodyNotFoundException
(
"Request don't have a body. "
+
"Please verify that this request is a Http POST/PUT/PATCH and request "
+
"content length is greater than zero before accessing the body."
);
}
...
...
@@ -135,16 +132,14 @@ namespace Titanium.Web.Proxy.EventArguments
if
(
WebSession
.
Request
.
ContentLength
>
0
)
{
//If not chunked then its easy just read the amount of bytes mentioned in content length header of response
await
ProxyClient
.
ClientStreamReader
.
CopyBytesToStream
(
requestBodyStream
,
WebSession
.
Request
.
ContentLength
);
await
ProxyClient
.
ClientStreamReader
.
CopyBytesToStream
(
requestBodyStream
,
WebSession
.
Request
.
ContentLength
);
}
else
if
(
WebSession
.
Request
.
HttpVersion
.
Major
==
1
&&
WebSession
.
Request
.
HttpVersion
.
Minor
==
0
)
{
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
requestBodyStream
,
long
.
MaxValue
);
}
}
WebSession
.
Request
.
RequestBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Request
.
ContentEncoding
,
requestBodyStream
.
ToArray
());
WebSession
.
Request
.
RequestBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Request
.
ContentEncoding
,
requestBodyStream
.
ToArray
());
}
//Now set the flag to true
...
...
@@ -185,17 +180,16 @@ namespace Titanium.Web.Proxy.EventArguments
if
(
WebSession
.
Response
.
ContentLength
>
0
)
{
//If not chunked then its easy just read the amount of bytes mentioned in content length header of response
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
responseBodyStream
,
WebSession
.
Response
.
ContentLength
);
await
WebSession
.
ServerConnection
.
StreamReader
.
CopyBytesToStream
(
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
(
responseBodyStream
,
long
.
MaxValue
);
}
}
WebSession
.
Response
.
ResponseBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Response
.
ContentEncoding
,
responseBodyStream
.
ToArray
());
WebSession
.
Response
.
ResponseBody
=
await
GetDecompressedResponseBody
(
WebSession
.
Response
.
ContentEncoding
,
responseBodyStream
.
ToArray
());
}
//set this to true for caching
WebSession
.
Response
.
ResponseBodyRead
=
true
;
...
...
@@ -236,7 +230,8 @@ namespace Titanium.Web.Proxy.EventArguments
await
ReadRequestBody
();
}
//Use the encoding specified in request to decode the byte[] data to string
return
WebSession
.
Request
.
RequestBodyString
??
(
WebSession
.
Request
.
RequestBodyString
=
WebSession
.
Request
.
Encoding
.
GetString
(
WebSession
.
Request
.
RequestBody
));
return
WebSession
.
Request
.
RequestBodyString
??
(
WebSession
.
Request
.
RequestBodyString
=
WebSession
.
Request
.
Encoding
.
GetString
(
WebSession
.
Request
.
RequestBody
));
}
/// <summary>
...
...
@@ -316,8 +311,8 @@ namespace Titanium.Web.Proxy.EventArguments
await
GetResponseBody
();
return
WebSession
.
Response
.
ResponseBodyString
??
(
WebSession
.
Response
.
ResponseBodyString
=
WebSession
.
Response
.
Encoding
.
GetString
(
WebSession
.
Response
.
ResponseBody
));
return
WebSession
.
Response
.
ResponseBodyString
??
(
WebSession
.
Response
.
ResponseBodyString
=
WebSession
.
Response
.
Encoding
.
GetString
(
WebSession
.
Response
.
ResponseBody
));
}
/// <summary>
...
...
Titanium.Web.Proxy/Exceptions/BodyNotFoundException.cs
View file @
70c107a4
...
...
@@ -9,8 +9,7 @@
/// Constructor.
/// </summary>
/// <param name="message"></param>
public
BodyNotFoundException
(
string
message
)
:
base
(
message
)
public
BodyNotFoundException
(
string
message
)
:
base
(
message
)
{
}
}
...
...
Titanium.Web.Proxy/Extensions/FuncExtensions.cs
View file @
70c107a4
...
...
@@ -7,8 +7,8 @@ namespace Titanium.Web.Proxy.Extensions
{
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
];
var
invocationList
=
callback
.
GetInvocationList
();
var
handlerTasks
=
new
Task
[
invocationList
.
Length
];
for
(
int
i
=
0
;
i
<
invocationList
.
Length
;
i
++)
{
...
...
@@ -20,8 +20,8 @@ namespace Titanium.Web.Proxy.Extensions
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
];
var
invocationList
=
callback
.
GetInvocationList
();
var
handlerTasks
=
new
Task
[
invocationList
.
Length
];
for
(
int
i
=
0
;
i
<
invocationList
.
Length
;
i
++)
{
...
...
Titanium.Web.Proxy/Extensions/HttpWebRequestExtensions.cs
View file @
70c107a4
using
System
;
using
System.Text
;
using
System.Text
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Http
;
...
...
Titanium.Web.Proxy/Extensions/HttpWebResponseExtensions.cs
View file @
70c107a4
using
System
;
using
System.Text
;
using
System.Text
;
using
Titanium.Web.Proxy.Helpers
;
using
Titanium.Web.Proxy.Http
;
...
...
Titanium.Web.Proxy/Extensions/StreamExtensions.cs
View file @
70c107a4
...
...
@@ -39,7 +39,7 @@ namespace Titanium.Web.Proxy.Extensions
/// <returns></returns>
internal
static
async
Task
CopyBytesToStream
(
this
CustomBinaryReader
streamReader
,
Stream
stream
,
long
totalBytesToRead
)
{
byte
[]
buffer
=
streamReader
.
Buffer
;
var
buffer
=
streamReader
.
Buffer
;
long
remainingBytes
=
totalBytesToRead
;
while
(
remainingBytes
>
0
)
...
...
@@ -72,8 +72,8 @@ namespace Titanium.Web.Proxy.Extensions
{
while
(
true
)
{
var
chuchkHead
=
await
clientStreamReader
.
ReadLineAsync
();
var
chunkSize
=
int
.
Parse
(
chuchkHead
,
NumberStyles
.
HexNumber
);
string
chuchkHead
=
await
clientStreamReader
.
ReadLineAsync
();
int
chunkSize
=
int
.
Parse
(
chuchkHead
,
NumberStyles
.
HexNumber
);
if
(
chunkSize
!=
0
)
{
...
...
@@ -119,7 +119,8 @@ namespace Titanium.Web.Proxy.Extensions
/// <param name="isChunked"></param>
/// <param name="contentLength"></param>
/// <returns></returns>
internal
static
async
Task
WriteResponseBody
(
this
CustomBinaryReader
inStreamReader
,
int
bufferSize
,
Stream
outStream
,
bool
isChunked
,
long
contentLength
)
internal
static
async
Task
WriteResponseBody
(
this
CustomBinaryReader
inStreamReader
,
int
bufferSize
,
Stream
outStream
,
bool
isChunked
,
long
contentLength
)
{
if
(!
isChunked
)
{
...
...
@@ -147,8 +148,8 @@ namespace Titanium.Web.Proxy.Extensions
{
while
(
true
)
{
var
chunkHead
=
await
inStreamReader
.
ReadLineAsync
();
var
chunkSize
=
int
.
Parse
(
chunkHead
,
NumberStyles
.
HexNumber
);
string
chunkHead
=
await
inStreamReader
.
ReadLineAsync
();
int
chunkSize
=
int
.
Parse
(
chunkHead
,
NumberStyles
.
HexNumber
);
if
(
chunkSize
!=
0
)
{
...
...
Titanium.Web.Proxy/Extensions/TcpExtensions.cs
View file @
70c107a4
...
...
@@ -13,7 +13,7 @@ namespace Titanium.Web.Proxy.Extensions
internal
static
bool
IsConnected
(
this
Socket
client
)
{
// This is how you can determine whether a socket is still connected.
var
blockingState
=
client
.
Blocking
;
bool
blockingState
=
client
.
Blocking
;
try
{
...
...
Titanium.Web.Proxy/Helpers/BufferPool.cs
View file @
70c107a4
using
System
;
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
System.Threading.Tasks
;
using
System.Collections.Concurrent
;
namespace
Titanium.Web.Proxy.Helpers
{
...
...
Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
View file @
70c107a4
...
...
@@ -34,7 +34,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns></returns>
internal
async
Task
<
string
>
ReadLineAsync
()
{
var
lastChar
=
default
(
byte
);
byte
lastChar
=
default
(
byte
);
int
bufferDataLength
=
0
;
...
...
@@ -43,7 +43,7 @@ namespace Titanium.Web.Proxy.Helpers
while
(
stream
.
DataAvailable
||
await
stream
.
FillBufferAsync
())
{
var
newChar
=
stream
.
ReadByteFromBuffer
();
byte
newChar
=
stream
.
ReadByteFromBuffer
();
buffer
[
bufferDataLength
]
=
newChar
;
//if new line
...
...
Titanium.Web.Proxy/Helpers/CustomBufferedStream.cs
View file @
70c107a4
...
...
@@ -35,7 +35,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="bufferSize">Size of the buffer.</param>
public
CustomBufferedStream
(
Stream
baseStream
,
int
bufferSize
)
{
readCallback
=
new
AsyncCallback
(
ReadCallback
)
;
readCallback
=
ReadCallback
;
this
.
baseStream
=
baseStream
;
streamBuffer
=
BufferPool
.
GetBuffer
(
bufferSize
);
}
...
...
@@ -359,7 +359,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
protected
override
void
Dispose
(
bool
disposing
)
{
if
(!
disposed
)
if
(!
disposed
)
{
disposed
=
true
;
baseStream
.
Dispose
();
...
...
@@ -367,7 +367,6 @@ namespace Titanium.Web.Proxy.Helpers
streamBuffer
=
null
;
readCallback
=
null
;
}
}
/// <summary>
...
...
Titanium.Web.Proxy/Helpers/Firefox.cs
View file @
70c107a4
...
...
@@ -16,9 +16,9 @@ namespace Titanium.Web.Proxy.Helpers
try
{
var
myProfileDirectory
=
new
DirectoryInfo
(
Environment
.
GetFolderPath
(
Environment
.
SpecialFolder
.
ApplicationData
)
+
"\\Mozilla\\Firefox\\Profiles\\"
)
.
GetDirectories
(
"*.default"
);
var
myFfPrefFile
=
myProfileDirectory
[
0
].
FullName
+
"\\prefs.js"
;
new
DirectoryInfo
(
Environment
.
GetFolderPath
(
Environment
.
SpecialFolder
.
ApplicationData
)
+
"\\Mozilla\\Firefox\\Profiles\\"
)
.
GetDirectories
(
"*.default"
);
string
myFfPrefFile
=
myProfileDirectory
[
0
].
FullName
+
"\\prefs.js"
;
if
(!
File
.
Exists
(
myFfPrefFile
))
{
return
;
...
...
@@ -26,18 +26,17 @@ namespace Titanium.Web.Proxy.Helpers
// We have a pref file so let''s make sure it has the proxy setting
var
myReader
=
new
StreamReader
(
myFfPrefFile
);
var
myPrefContents
=
myReader
.
ReadToEnd
();
string
myPrefContents
=
myReader
.
ReadToEnd
();
myReader
.
Close
();
for
(
int
i
=
0
;
i
<=
4
;
i
++)
{
var
searchStr
=
$"user_pref(\"network.proxy.type\",
{
i
}
);"
;
string
searchStr
=
$"user_pref(\"network.proxy.type\",
{
i
}
);"
;
if
(
myPrefContents
.
Contains
(
searchStr
))
{
// Add the proxy enable line and write it back to the file
myPrefContents
=
myPrefContents
.
Replace
(
searchStr
,
"user_pref(\"network.proxy.type\", 5);"
);
myPrefContents
=
myPrefContents
.
Replace
(
searchStr
,
"user_pref(\"network.proxy.type\", 5);"
);
}
}
...
...
Titanium.Web.Proxy/Helpers/HttpHelper.cs
View file @
70c107a4
...
...
@@ -20,7 +20,7 @@ namespace Titanium.Web.Proxy.Helpers
//extract the encoding by finding the charset
var
parameters
=
contentType
.
Split
(
ProxyConstants
.
SemiColonSplit
);
foreach
(
var
parameter
in
parameters
)
foreach
(
string
parameter
in
parameters
)
{
var
encodingSplit
=
parameter
.
Split
(
ProxyConstants
.
EqualSplit
,
2
);
if
(
encodingSplit
.
Length
==
2
&&
encodingSplit
[
0
].
Trim
().
Equals
(
"charset"
,
StringComparison
.
CurrentCultureIgnoreCase
))
...
...
@@ -66,9 +66,8 @@ namespace Titanium.Web.Proxy.Helpers
if
(
hostname
.
Split
(
ProxyConstants
.
DotSplit
).
Length
>
2
)
{
int
idx
=
hostname
.
IndexOf
(
ProxyConstants
.
DotSplit
);
var
rootDomain
=
hostname
.
Substring
(
idx
+
1
);
string
rootDomain
=
hostname
.
Substring
(
idx
+
1
);
return
"*."
+
rootDomain
;
}
//return as it is
...
...
Titanium.Web.Proxy/Helpers/Network.cs
View file @
70c107a4
...
...
@@ -15,7 +15,7 @@ namespace Titanium.Web.Proxy.Helpers
internal
static
int
GetProcessIdFromPort
(
int
port
,
bool
ipV6Enabled
)
{
var
processId
=
FindProcessIdFromLocalPort
(
port
,
IpVersion
.
Ipv4
);
int
processId
=
FindProcessIdFromLocalPort
(
port
,
IpVersion
.
Ipv4
);
if
(
processId
>
0
&&
!
ipV6Enabled
)
{
...
...
@@ -43,10 +43,10 @@ namespace Titanium.Web.Proxy.Helpers
{
bool
isLocalhost
=
false
;
IPHostEntry
localhost
=
Dns
.
GetHostEntry
(
"127.0.0.1"
);
var
localhost
=
Dns
.
GetHostEntry
(
"127.0.0.1"
);
if
(
hostName
==
localhost
.
HostName
)
{
IPHostEntry
hostEntry
=
Dns
.
GetHostEntry
(
hostName
);
var
hostEntry
=
Dns
.
GetHostEntry
(
hostName
);
isLocalhost
=
hostEntry
.
AddressList
.
Any
(
IPAddress
.
IsLoopback
);
}
...
...
Titanium.Web.Proxy/Helpers/ProxyInfo.cs
View file @
70c107a4
...
...
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using
System.Linq
;
using
System.Text
;
using
System.Text.RegularExpressions
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Helpers
{
...
...
@@ -37,14 +36,14 @@ namespace Titanium.Web.Proxy.Helpers
if
(
proxyServer
!=
null
)
{
Proxies
=
GetSystemProxyValues
(
proxyServer
).
ToDictionary
(
x
=>
x
.
ProtocolType
);
Proxies
=
GetSystemProxyValues
(
proxyServer
).
ToDictionary
(
x
=>
x
.
ProtocolType
);
}
if
(
proxyOverride
!=
null
)
{
var
overrides
=
proxyOverride
.
Split
(
';'
);
var
overrides2
=
new
List
<
string
>();
foreach
(
var
overrideHost
in
overrides
)
foreach
(
string
overrideHost
in
overrides
)
{
if
(
overrideHost
==
"<-loopback>"
)
{
...
...
@@ -71,7 +70,8 @@ namespace Titanium.Web.Proxy.Helpers
private
static
string
BypassStringEscape
(
string
rawString
)
{
Match
match
=
new
Regex
(
"^(?<scheme>.*://)?(?<host>[^:]*)(?<port>:[0-9]{1,5})?$"
,
RegexOptions
.
IgnoreCase
|
RegexOptions
.
CultureInvariant
).
Match
(
rawString
);
var
match
=
new
Regex
(
"^(?<scheme>.*://)?(?<host>[^:]*)(?<port>:[0-9]{1,5})?$"
,
RegexOptions
.
IgnoreCase
|
RegexOptions
.
CultureInvariant
).
Match
(
rawString
);
string
empty1
;
string
rawString1
;
string
empty2
;
...
...
@@ -174,7 +174,7 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns></returns>
private
static
HttpSystemProxyValue
ParseProxyValue
(
string
value
)
{
var
tmp
=
Regex
.
Replace
(
value
,
@"\s+"
,
" "
).
Trim
();
string
tmp
=
Regex
.
Replace
(
value
,
@"\s+"
,
" "
).
Trim
();
int
equalsIndex
=
tmp
.
IndexOf
(
"="
,
StringComparison
.
InvariantCulture
);
if
(
equalsIndex
>=
0
)
...
...
Titanium.Web.Proxy/Helpers/RunTime.cs
View file @
70c107a4
...
...
@@ -11,9 +11,8 @@ namespace Titanium.Web.Proxy.Helpers
/// cache for mono runtime check
/// </summary>
/// <returns></returns>
private
static
Lazy
<
bool
>
isRunningOnMono
=
new
Lazy
<
bool
>(()=>
Type
.
GetType
(
"Mono.Runtime"
)
!=
null
);
private
static
readonly
Lazy
<
bool
>
isRunningOnMono
=
new
Lazy
<
bool
>(()
=>
Type
.
GetType
(
"Mono.Runtime"
)
!=
null
);
/// <summary>
/// Is running on Mono?
/// </summary>
...
...
Titanium.Web.Proxy/Helpers/SystemProxy.cs
View file @
70c107a4
using
System
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Runtime.InteropServices
;
using
Microsoft.Win32
;
...
...
@@ -34,8 +33,7 @@ namespace Titanium.Web.Proxy.Helpers
internal
partial
class
NativeMethods
{
[
DllImport
(
"wininet.dll"
)]
internal
static
extern
bool
InternetSetOption
(
IntPtr
hInternet
,
int
dwOption
,
IntPtr
lpBuffer
,
int
dwBufferLength
);
internal
static
extern
bool
InternetSetOption
(
IntPtr
hInternet
,
int
dwOption
,
IntPtr
lpBuffer
,
int
dwBufferLength
);
[
DllImport
(
"kernel32.dll"
)]
internal
static
extern
IntPtr
GetConsoleWindow
();
...
...
@@ -129,7 +127,7 @@ namespace Titanium.Web.Proxy.Helpers
SaveOriginalProxyConfiguration
(
reg
);
PrepareRegistry
(
reg
);
var
exisitingContent
=
reg
.
GetValue
(
regProxyServer
)
as
string
;
string
exisitingContent
=
reg
.
GetValue
(
regProxyServer
)
as
string
;
var
existingSystemProxyValues
=
ProxyInfo
.
GetSystemProxyValues
(
exisitingContent
);
existingSystemProxyValues
.
RemoveAll
(
x
=>
(
protocolType
&
x
.
ProtocolType
)
!=
0
);
if
((
protocolType
&
ProxyProtocolType
.
Http
)
!=
0
)
...
...
@@ -175,7 +173,7 @@ namespace Titanium.Web.Proxy.Helpers
if
(
reg
.
GetValue
(
regProxyServer
)
!=
null
)
{
var
exisitingContent
=
reg
.
GetValue
(
regProxyServer
)
as
string
;
string
exisitingContent
=
reg
.
GetValue
(
regProxyServer
)
as
string
;
var
existingSystemProxyValues
=
ProxyInfo
.
GetSystemProxyValues
(
exisitingContent
);
existingSystemProxyValues
.
RemoveAll
(
x
=>
(
protocolType
&
x
.
ProtocolType
)
!=
0
);
...
...
@@ -305,11 +303,7 @@ namespace Titanium.Web.Proxy.Helpers
private
ProxyInfo
GetProxyInfoFromRegistry
(
RegistryKey
reg
)
{
var
pi
=
new
ProxyInfo
(
null
,
reg
.
GetValue
(
regAutoConfigUrl
)
as
string
,
reg
.
GetValue
(
regProxyEnable
)
as
int
?,
reg
.
GetValue
(
regProxyServer
)
as
string
,
var
pi
=
new
ProxyInfo
(
null
,
reg
.
GetValue
(
regAutoConfigUrl
)
as
string
,
reg
.
GetValue
(
regProxyEnable
)
as
int
?,
reg
.
GetValue
(
regProxyServer
)
as
string
,
reg
.
GetValue
(
regProxyOverride
)
as
string
);
return
pi
;
...
...
Titanium.Web.Proxy/Helpers/Tcp.cs
View file @
70c107a4
...
...
@@ -83,12 +83,12 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns>Collection of <see cref="TcpRow"/>.</returns>
internal
static
TcpTable
GetExtendedTcpTable
(
IpVersion
ipVersion
)
{
List
<
TcpRow
>
tcpRows
=
new
List
<
TcpRow
>();
var
tcpRows
=
new
List
<
TcpRow
>();
IntPt
r
tcpTable
=
IntPtr
.
Zero
;
va
r
tcpTable
=
IntPtr
.
Zero
;
int
tcpTableLength
=
0
;
var
ipVersionValue
=
ipVersion
==
IpVersion
.
Ipv4
?
NativeMethods
.
AfInet
:
NativeMethods
.
AfInet6
;
int
ipVersionValue
=
ipVersion
==
IpVersion
.
Ipv4
?
NativeMethods
.
AfInet
:
NativeMethods
.
AfInet6
;
if
(
NativeMethods
.
GetExtendedTcpTable
(
tcpTable
,
ref
tcpTableLength
,
false
,
ipVersionValue
,
(
int
)
NativeMethods
.
TcpTableType
.
OwnerPidAll
,
0
)
!=
0
)
{
...
...
@@ -97,9 +97,9 @@ namespace Titanium.Web.Proxy.Helpers
tcpTable
=
Marshal
.
AllocHGlobal
(
tcpTableLength
);
if
(
NativeMethods
.
GetExtendedTcpTable
(
tcpTable
,
ref
tcpTableLength
,
true
,
ipVersionValue
,
(
int
)
NativeMethods
.
TcpTableType
.
OwnerPidAll
,
0
)
==
0
)
{
NativeMethods
.
TcpTable
table
=
(
NativeMethods
.
TcpTable
)
Marshal
.
PtrToStructure
(
tcpTable
,
typeof
(
NativeMethods
.
TcpTable
));
var
table
=
(
NativeMethods
.
TcpTable
)
Marshal
.
PtrToStructure
(
tcpTable
,
typeof
(
NativeMethods
.
TcpTable
));
IntPt
r
rowPtr
=
(
IntPtr
)((
long
)
tcpTable
+
Marshal
.
SizeOf
(
table
.
length
));
va
r
rowPtr
=
(
IntPtr
)((
long
)
tcpTable
+
Marshal
.
SizeOf
(
table
.
length
));
for
(
int
i
=
0
;
i
<
table
.
length
;
++
i
)
{
...
...
@@ -126,10 +126,10 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns><see cref="TcpRow"/>.</returns>
internal
static
TcpRow
GetTcpRowByLocalPort
(
IpVersion
ipVersion
,
int
localPort
)
{
IntPt
r
tcpTable
=
IntPtr
.
Zero
;
va
r
tcpTable
=
IntPtr
.
Zero
;
int
tcpTableLength
=
0
;
var
ipVersionValue
=
ipVersion
==
IpVersion
.
Ipv4
?
NativeMethods
.
AfInet
:
NativeMethods
.
AfInet6
;
int
ipVersionValue
=
ipVersion
==
IpVersion
.
Ipv4
?
NativeMethods
.
AfInet
:
NativeMethods
.
AfInet6
;
if
(
NativeMethods
.
GetExtendedTcpTable
(
tcpTable
,
ref
tcpTableLength
,
false
,
ipVersionValue
,
(
int
)
NativeMethods
.
TcpTableType
.
OwnerPidAll
,
0
)
!=
0
)
{
...
...
@@ -138,9 +138,9 @@ namespace Titanium.Web.Proxy.Helpers
tcpTable
=
Marshal
.
AllocHGlobal
(
tcpTableLength
);
if
(
NativeMethods
.
GetExtendedTcpTable
(
tcpTable
,
ref
tcpTableLength
,
true
,
ipVersionValue
,
(
int
)
NativeMethods
.
TcpTableType
.
OwnerPidAll
,
0
)
==
0
)
{
NativeMethods
.
TcpTable
table
=
(
NativeMethods
.
TcpTable
)
Marshal
.
PtrToStructure
(
tcpTable
,
typeof
(
NativeMethods
.
TcpTable
));
var
table
=
(
NativeMethods
.
TcpTable
)
Marshal
.
PtrToStructure
(
tcpTable
,
typeof
(
NativeMethods
.
TcpTable
));
IntPt
r
rowPtr
=
(
IntPtr
)((
long
)
tcpTable
+
Marshal
.
SizeOf
(
table
.
length
));
va
r
rowPtr
=
(
IntPtr
)((
long
)
tcpTable
+
Marshal
.
SizeOf
(
table
.
length
));
for
(
int
i
=
0
;
i
<
table
.
length
;
++
i
)
{
...
...
@@ -181,11 +181,8 @@ namespace Titanium.Web.Proxy.Helpers
/// <param name="tcpConnectionFactory"></param>
/// <param name="connection"></param>
/// <returns></returns>
internal
static
async
Task
SendRaw
(
ProxyServer
server
,
string
remoteHostName
,
int
remotePort
,
string
httpCmd
,
Version
httpVersion
,
Dictionary
<
string
,
HttpHeader
>
requestHeaders
,
bool
isHttps
,
Stream
clientStream
,
TcpConnectionFactory
tcpConnectionFactory
,
internal
static
async
Task
SendRaw
(
ProxyServer
server
,
string
remoteHostName
,
int
remotePort
,
string
httpCmd
,
Version
httpVersion
,
Dictionary
<
string
,
HttpHeader
>
requestHeaders
,
bool
isHttps
,
Stream
clientStream
,
TcpConnectionFactory
tcpConnectionFactory
,
TcpConnection
connection
=
null
)
{
//prepare the prefix content
...
...
@@ -202,7 +199,7 @@ namespace Titanium.Web.Proxy.Helpers
if
(
requestHeaders
!=
null
)
{
foreach
(
var
header
in
requestHeaders
.
Select
(
t
=>
t
.
Value
.
ToString
()))
foreach
(
string
header
in
requestHeaders
.
Select
(
t
=>
t
.
Value
.
ToString
()))
{
sb
.
Append
(
header
);
sb
.
Append
(
ProxyConstants
.
NewLine
);
...
...
@@ -218,10 +215,7 @@ namespace Titanium.Web.Proxy.Helpers
//create new connection if connection is null
if
(
connection
==
null
)
{
tcpConnection
=
await
tcpConnectionFactory
.
CreateClient
(
server
,
remoteHostName
,
remotePort
,
httpVersion
,
isHttps
,
null
,
null
);
tcpConnection
=
await
tcpConnectionFactory
.
CreateClient
(
server
,
remoteHostName
,
remotePort
,
httpVersion
,
isHttps
,
null
,
null
);
connectionCreated
=
true
;
}
...
...
@@ -232,7 +226,7 @@ namespace Titanium.Web.Proxy.Helpers
try
{
Stream
tunnelStream
=
tcpConnection
.
Stream
;
var
tunnelStream
=
tcpConnection
.
Stream
;
//Now async relay all server=>client & client=>server data
var
sendRelay
=
clientStream
.
CopyToAsync
(
sb
?.
ToString
()
??
string
.
Empty
,
tunnelStream
);
...
...
Titanium.Web.Proxy/Helpers/WinHttp/NativeMethods.WinHttp.cs
View file @
70c107a4
...
...
@@ -18,7 +18,8 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
internal
static
extern
bool
WinHttpSetTimeouts
(
WinHttpHandle
session
,
int
resolveTimeout
,
int
connectTimeout
,
int
sendTimeout
,
int
receiveTimeout
);
[
DllImport
(
"winhttp.dll"
,
CharSet
=
CharSet
.
Unicode
,
SetLastError
=
true
)]
internal
static
extern
bool
WinHttpGetProxyForUrl
(
WinHttpHandle
session
,
string
url
,
[
In
]
ref
WINHTTP_AUTOPROXY_OPTIONS
autoProxyOptions
,
out
WINHTTP_PROXY_INFO
proxyInfo
);
internal
static
extern
bool
WinHttpGetProxyForUrl
(
WinHttpHandle
session
,
string
url
,
[
In
]
ref
WINHTTP_AUTOPROXY_OPTIONS
autoProxyOptions
,
out
WINHTTP_PROXY_INFO
proxyInfo
);
[
DllImport
(
"winhttp.dll"
,
CharSet
=
CharSet
.
Unicode
,
SetLastError
=
true
)]
internal
static
extern
bool
WinHttpCloseHandle
(
IntPtr
httpSession
);
...
...
@@ -62,8 +63,8 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
public
AutoProxyFlags
Flags
;
public
AutoDetectType
AutoDetectFlags
;
[
MarshalAs
(
UnmanagedType
.
LPWStr
)]
public
string
AutoConfigUrl
;
private
IntPtr
lpvReserved
;
private
int
dwReserved
;
private
readonly
IntPtr
lpvReserved
;
private
readonly
int
dwReserved
;
public
bool
AutoLogonIfChallenged
;
}
...
...
Titanium.Web.Proxy/Helpers/WinHttp/WinHttpHandle.cs
View file @
70c107a4
...
...
@@ -16,4 +16,4 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
public
override
bool
IsInvalid
=>
handle
==
IntPtr
.
Zero
;
}
}
\ No newline at end of file
}
Titanium.Web.Proxy/Helpers/WinHttp/WinHttpWebProxyFinder.cs
View file @
70c107a4
...
...
@@ -21,12 +21,12 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
public
bool
BypassLoopback
{
get
;
internal
set
;
}
public
bool
BypassOnLocal
{
get
;
internal
set
;
}
public
Uri
AutomaticConfigurationScript
{
get
;
internal
set
;
}
public
bool
AutomaticallyDetectSettings
{
get
;
internal
set
;
}
private
WebProxy
P
roxy
{
get
;
set
;
}
private
WebProxy
p
roxy
{
get
;
set
;
}
public
WinHttpWebProxyFinder
()
{
...
...
@@ -89,26 +89,26 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
return
null
;
}
string
proxy
=
proxies
[
0
];
string
proxy
Str
=
proxies
[
0
];
int
port
=
80
;
if
(
proxy
.
Contains
(
":"
))
if
(
proxy
Str
.
Contains
(
":"
))
{
var
parts
=
proxy
.
Split
(
new
[]
{
':'
},
2
);
proxy
=
parts
[
0
];
var
parts
=
proxy
Str
.
Split
(
new
[]
{
':'
},
2
);
proxy
Str
=
parts
[
0
];
port
=
int
.
Parse
(
parts
[
1
]);
}
// TODO: Apply authorization
var
systemProxy
=
new
ExternalProxy
{
HostName
=
proxy
,
HostName
=
proxy
Str
,
Port
=
port
,
};
return
systemProxy
;
}
if
(
P
roxy
?.
IsBypassed
(
destination
)
==
true
)
if
(
p
roxy
?.
IsBypassed
(
destination
)
==
true
)
return
null
;
var
protocolType
=
ProxyInfo
.
ParseProtocolType
(
destination
.
Scheme
);
...
...
@@ -138,7 +138,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
AutomaticConfigurationScript
=
pi
.
AutoConfigUrl
==
null
?
null
:
new
Uri
(
pi
.
AutoConfigUrl
);
BypassLoopback
=
pi
.
BypassLoopback
;
BypassOnLocal
=
pi
.
BypassOnLocal
;
P
roxy
=
new
WebProxy
(
new
Uri
(
"http://localhost"
),
BypassOnLocal
,
pi
.
BypassList
);
p
roxy
=
new
WebProxy
(
new
Uri
(
"http://localhost"
),
BypassOnLocal
,
pi
.
BypassList
);
}
private
ProxyInfo
GetProxyInfo
()
...
...
@@ -214,7 +214,7 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
if
(!
WinHttpGetProxyForUrl
(
destination
.
ToString
(),
ref
autoProxyOptions
,
out
proxyListString
))
{
num
=
GetLastWin32Error
();
if
(
num
==
(
int
)
NativeMethods
.
WinHttp
.
ErrorCodes
.
LoginFailure
&&
Credentials
!=
null
)
{
autoProxyOptions
.
AutoLogonIfChallenged
=
true
;
...
...
@@ -329,4 +329,4 @@ namespace Titanium.Web.Proxy.Helpers.WinHttp
Completed
,
}
}
}
\ No newline at end of file
}
Titanium.Web.Proxy/Http/HeaderParser.cs
View file @
70c107a4
...
...
@@ -8,8 +8,7 @@ namespace Titanium.Web.Proxy.Http
{
internal
static
class
HeaderParser
{
internal
static
async
Task
ReadHeaders
(
CustomBinaryReader
reader
,
Dictionary
<
string
,
List
<
HttpHeader
>>
nonUniqueResponseHeaders
,
internal
static
async
Task
ReadHeaders
(
CustomBinaryReader
reader
,
Dictionary
<
string
,
List
<
HttpHeader
>>
nonUniqueResponseHeaders
,
Dictionary
<
string
,
HttpHeader
>
headers
)
{
string
tmpLine
;
...
...
@@ -29,7 +28,11 @@ namespace Titanium.Web.Proxy.Http
{
var
existing
=
headers
[
newHeader
.
Name
];
var
nonUniqueHeaders
=
new
List
<
HttpHeader
>
{
existing
,
newHeader
};
var
nonUniqueHeaders
=
new
List
<
HttpHeader
>
{
existing
,
newHeader
};
nonUniqueResponseHeaders
.
Add
(
newHeader
.
Name
,
nonUniqueHeaders
);
headers
.
Remove
(
newHeader
.
Name
);
...
...
Titanium.Web.Proxy/Http/HttpWebClient.cs
View file @
70c107a4
...
...
@@ -84,8 +84,8 @@ namespace Titanium.Web.Proxy.Http
//Send Authentication to Upstream proxy if needed
if
(
ServerConnection
.
UpStreamHttpProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
if
(
ServerConnection
.
UpStreamHttpProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
&&
!
string
.
IsNullOrEmpty
(
ServerConnection
.
UpStreamHttpProxy
.
UserName
)
&&
ServerConnection
.
UpStreamHttpProxy
.
Password
!=
null
)
{
...
...
@@ -118,7 +118,7 @@ namespace Titanium.Web.Proxy.Http
requestLines
.
AppendLine
();
var
request
=
requestLines
.
ToString
();
string
request
=
requestLines
.
ToString
();
var
requestBytes
=
Encoding
.
ASCII
.
GetBytes
(
request
);
await
stream
.
WriteAsync
(
requestBytes
,
0
,
requestBytes
.
Length
);
...
...
@@ -129,8 +129,8 @@ namespace Titanium.Web.Proxy.Http
if
(
Request
.
ExpectContinue
)
{
var
httpResult
=
(
await
ServerConnection
.
StreamReader
.
ReadLineAsync
()).
Split
(
ProxyConstants
.
SpaceSplit
,
3
);
var
responseStatusCode
=
httpResult
[
1
].
Trim
();
var
responseStatusDescription
=
httpResult
[
2
].
Trim
();
string
responseStatusCode
=
httpResult
[
1
].
Trim
();
string
responseStatusDescription
=
httpResult
[
2
].
Trim
();
//find if server is willing for expect continue
if
(
responseStatusCode
.
Equals
(
"100"
)
...
...
@@ -156,7 +156,8 @@ namespace Titanium.Web.Proxy.Http
internal
async
Task
ReceiveResponse
()
{
//return if this is already read
if
(
Response
.
ResponseStatusCode
!=
null
)
return
;
if
(
Response
.
ResponseStatusCode
!=
null
)
return
;
string
line
=
await
ServerConnection
.
StreamReader
.
ReadLineAsync
();
if
(
line
==
null
)
...
...
@@ -172,7 +173,7 @@ namespace Titanium.Web.Proxy.Http
httpResult
=
(
await
ServerConnection
.
StreamReader
.
ReadLineAsync
()).
Split
(
ProxyConstants
.
SpaceSplit
,
3
);
}
var
httpVersion
=
httpResult
[
0
];
string
httpVersion
=
httpResult
[
0
];
var
version
=
HttpHeader
.
Version11
;
if
(
string
.
Equals
(
httpVersion
,
"HTTP/1.0"
,
StringComparison
.
OrdinalIgnoreCase
))
...
...
Titanium.Web.Proxy/Http/Request.cs
View file @
70c107a4
using
System
;
using
System.Linq
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Text
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Models
;
...
...
@@ -41,12 +41,12 @@ namespace Titanium.Web.Proxy.Http
{
get
{
var
hasHeader
=
RequestHeaders
.
ContainsKey
(
"host"
);
bool
hasHeader
=
RequestHeaders
.
ContainsKey
(
"host"
);
return
hasHeader
?
RequestHeaders
[
"host"
].
Value
:
null
;
}
set
{
var
hasHeader
=
RequestHeaders
.
ContainsKey
(
"host"
);
bool
hasHeader
=
RequestHeaders
.
ContainsKey
(
"host"
);
if
(
hasHeader
)
{
RequestHeaders
[
"host"
].
Value
=
value
;
...
...
@@ -65,7 +65,7 @@ namespace Titanium.Web.Proxy.Http
{
get
{
var
hasHeader
=
RequestHeaders
.
ContainsKey
(
"content-encoding"
);
bool
hasHeader
=
RequestHeaders
.
ContainsKey
(
"content-encoding"
);
if
(
hasHeader
)
{
...
...
@@ -83,7 +83,7 @@ namespace Titanium.Web.Proxy.Http
{
get
{
var
hasHeader
=
RequestHeaders
.
ContainsKey
(
"content-length"
);
bool
hasHeader
=
RequestHeaders
.
ContainsKey
(
"content-length"
);
if
(
hasHeader
==
false
)
{
...
...
@@ -103,7 +103,7 @@ namespace Titanium.Web.Proxy.Http
}
set
{
var
hasHeader
=
RequestHeaders
.
ContainsKey
(
"content-length"
);
bool
hasHeader
=
RequestHeaders
.
ContainsKey
(
"content-length"
);
var
header
=
RequestHeaders
[
"content-length"
];
...
...
@@ -137,7 +137,7 @@ namespace Titanium.Web.Proxy.Http
{
get
{
var
hasHeader
=
RequestHeaders
.
ContainsKey
(
"content-type"
);
bool
hasHeader
=
RequestHeaders
.
ContainsKey
(
"content-type"
);
if
(
hasHeader
)
{
...
...
@@ -149,7 +149,7 @@ namespace Titanium.Web.Proxy.Http
}
set
{
var
hasHeader
=
RequestHeaders
.
ContainsKey
(
"content-type"
);
bool
hasHeader
=
RequestHeaders
.
ContainsKey
(
"content-type"
);
if
(
hasHeader
)
{
...
...
@@ -170,7 +170,7 @@ namespace Titanium.Web.Proxy.Http
{
get
{
var
hasHeader
=
RequestHeaders
.
ContainsKey
(
"transfer-encoding"
);
bool
hasHeader
=
RequestHeaders
.
ContainsKey
(
"transfer-encoding"
);
if
(
hasHeader
)
{
...
...
@@ -183,7 +183,7 @@ namespace Titanium.Web.Proxy.Http
}
set
{
var
hasHeader
=
RequestHeaders
.
ContainsKey
(
"transfer-encoding"
);
bool
hasHeader
=
RequestHeaders
.
ContainsKey
(
"transfer-encoding"
);
if
(
value
)
{
...
...
@@ -216,9 +216,10 @@ namespace Titanium.Web.Proxy.Http
{
get
{
var
hasHeader
=
RequestHeaders
.
ContainsKey
(
"expect"
);
bool
hasHeader
=
RequestHeaders
.
ContainsKey
(
"expect"
);
if
(!
hasHeader
)
return
false
;
if
(!
hasHeader
)
return
false
;
var
header
=
RequestHeaders
[
"expect"
];
return
header
.
Value
.
Equals
(
"100-continue"
);
...
...
@@ -267,7 +268,7 @@ namespace Titanium.Web.Proxy.Http
{
get
{
var
hasHeader
=
RequestHeaders
.
ContainsKey
(
"upgrade"
);
bool
hasHeader
=
RequestHeaders
.
ContainsKey
(
"upgrade"
);
if
(
hasHeader
==
false
)
{
...
...
@@ -317,8 +318,7 @@ namespace Titanium.Web.Proxy.Http
/// <returns></returns>
public
bool
HeaderExists
(
string
name
)
{
if
(
RequestHeaders
.
ContainsKey
(
name
)
||
NonUniqueRequestHeaders
.
ContainsKey
(
name
))
if
(
RequestHeaders
.
ContainsKey
(
name
)
||
NonUniqueRequestHeaders
.
ContainsKey
(
name
))
{
return
true
;
}
...
...
@@ -336,9 +336,12 @@ namespace Titanium.Web.Proxy.Http
{
if
(
RequestHeaders
.
ContainsKey
(
name
))
{
return
new
List
<
HttpHeader
>()
{
RequestHeaders
[
name
]
};
return
new
List
<
HttpHeader
>
{
RequestHeaders
[
name
]
};
}
else
if
(
NonUniqueRequestHeaders
.
ContainsKey
(
name
))
if
(
NonUniqueRequestHeaders
.
ContainsKey
(
name
))
{
return
new
List
<
HttpHeader
>(
NonUniqueRequestHeaders
[
name
]);
}
...
...
@@ -387,8 +390,11 @@ namespace Titanium.Web.Proxy.Http
var
existing
=
RequestHeaders
[
newHeader
.
Name
];
RequestHeaders
.
Remove
(
newHeader
.
Name
);
NonUniqueRequestHeaders
.
Add
(
newHeader
.
Name
,
new
List
<
HttpHeader
>()
{
existing
,
newHeader
});
NonUniqueRequestHeaders
.
Add
(
newHeader
.
Name
,
new
List
<
HttpHeader
>
{
existing
,
newHeader
});
}
else
{
...
...
@@ -409,7 +415,7 @@ namespace Titanium.Web.Proxy.Http
RequestHeaders
.
Remove
(
headerName
);
return
true
;
}
else
if
(
NonUniqueRequestHeaders
.
ContainsKey
(
headerName
))
if
(
NonUniqueRequestHeaders
.
ContainsKey
(
headerName
))
{
NonUniqueRequestHeaders
.
Remove
(
headerName
);
return
true
;
...
...
@@ -431,12 +437,10 @@ namespace Titanium.Web.Proxy.Http
RequestHeaders
.
Remove
(
header
.
Name
);
return
true
;
}
}
else
if
(
NonUniqueRequestHeaders
.
ContainsKey
(
header
.
Name
))
{
if
(
NonUniqueRequestHeaders
[
header
.
Name
]
.
RemoveAll
(
x
=>
x
.
Equals
(
header
))
>
0
)
if
(
NonUniqueRequestHeaders
[
header
.
Name
].
RemoveAll
(
x
=>
x
.
Equals
(
header
))
>
0
)
{
return
true
;
}
...
...
@@ -460,7 +464,5 @@ namespace Titanium.Web.Proxy.Http
RequestBody
=
null
;
RequestBody
=
null
;
}
}
}
Titanium.Web.Proxy/Http/Response.cs
View file @
70c107a4
using
System
;
using
System.Linq
;
using
System.Collections.Generic
;
using
System.
IO
;
using
System.
Linq
;
using
System.Text
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Models
;
...
...
@@ -35,9 +34,10 @@ namespace Titanium.Web.Proxy.Http
{
get
{
var
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"content-encoding"
);
bool
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"content-encoding"
);
if
(!
hasHeader
)
return
null
;
if
(!
hasHeader
)
return
null
;
var
header
=
ResponseHeaders
[
"content-encoding"
];
return
header
.
Value
.
Trim
();
...
...
@@ -56,7 +56,7 @@ namespace Titanium.Web.Proxy.Http
{
get
{
var
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"connection"
);
bool
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"connection"
);
if
(
hasHeader
)
{
...
...
@@ -79,7 +79,7 @@ namespace Titanium.Web.Proxy.Http
{
get
{
var
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"content-type"
);
bool
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"content-type"
);
if
(
hasHeader
)
{
...
...
@@ -99,7 +99,7 @@ namespace Titanium.Web.Proxy.Http
{
get
{
var
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"content-length"
);
bool
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"content-length"
);
if
(
hasHeader
==
false
)
{
...
...
@@ -119,7 +119,7 @@ namespace Titanium.Web.Proxy.Http
}
set
{
var
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"content-length"
);
bool
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"content-length"
);
if
(
value
>=
0
)
{
...
...
@@ -152,7 +152,7 @@ namespace Titanium.Web.Proxy.Http
{
get
{
var
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"transfer-encoding"
);
bool
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"transfer-encoding"
);
if
(
hasHeader
)
{
...
...
@@ -168,7 +168,7 @@ namespace Titanium.Web.Proxy.Http
}
set
{
var
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"transfer-encoding"
);
bool
hasHeader
=
ResponseHeaders
.
ContainsKey
(
"transfer-encoding"
);
if
(
value
)
{
...
...
@@ -250,8 +250,7 @@ namespace Titanium.Web.Proxy.Http
/// <returns></returns>
public
bool
HeaderExists
(
string
name
)
{
if
(
ResponseHeaders
.
ContainsKey
(
name
)
||
NonUniqueResponseHeaders
.
ContainsKey
(
name
))
if
(
ResponseHeaders
.
ContainsKey
(
name
)
||
NonUniqueResponseHeaders
.
ContainsKey
(
name
))
{
return
true
;
}
...
...
@@ -269,9 +268,12 @@ namespace Titanium.Web.Proxy.Http
{
if
(
ResponseHeaders
.
ContainsKey
(
name
))
{
return
new
List
<
HttpHeader
>()
{
ResponseHeaders
[
name
]
};
return
new
List
<
HttpHeader
>
{
ResponseHeaders
[
name
]
};
}
else
if
(
NonUniqueResponseHeaders
.
ContainsKey
(
name
))
if
(
NonUniqueResponseHeaders
.
ContainsKey
(
name
))
{
return
new
List
<
HttpHeader
>(
NonUniqueResponseHeaders
[
name
]);
}
...
...
@@ -320,8 +322,11 @@ namespace Titanium.Web.Proxy.Http
var
existing
=
ResponseHeaders
[
newHeader
.
Name
];
ResponseHeaders
.
Remove
(
newHeader
.
Name
);
NonUniqueResponseHeaders
.
Add
(
newHeader
.
Name
,
new
List
<
HttpHeader
>()
{
existing
,
newHeader
});
NonUniqueResponseHeaders
.
Add
(
newHeader
.
Name
,
new
List
<
HttpHeader
>
{
existing
,
newHeader
});
}
else
{
...
...
@@ -337,12 +342,12 @@ namespace Titanium.Web.Proxy.Http
/// False if no header exists with given name</returns>
public
bool
RemoveHeader
(
string
headerName
)
{
if
(
ResponseHeaders
.
ContainsKey
(
headerName
))
if
(
ResponseHeaders
.
ContainsKey
(
headerName
))
{
ResponseHeaders
.
Remove
(
headerName
);
return
true
;
}
else
if
(
NonUniqueResponseHeaders
.
ContainsKey
(
headerName
))
if
(
NonUniqueResponseHeaders
.
ContainsKey
(
headerName
))
{
NonUniqueResponseHeaders
.
Remove
(
headerName
);
return
true
;
...
...
@@ -364,12 +369,10 @@ namespace Titanium.Web.Proxy.Http
ResponseHeaders
.
Remove
(
header
.
Name
);
return
true
;
}
}
else
if
(
NonUniqueResponseHeaders
.
ContainsKey
(
header
.
Name
))
{
if
(
NonUniqueResponseHeaders
[
header
.
Name
]
.
RemoveAll
(
x
=>
x
.
Equals
(
header
))
>
0
)
if
(
NonUniqueResponseHeaders
[
header
.
Name
].
RemoveAll
(
x
=>
x
.
Equals
(
header
))
>
0
)
{
return
true
;
}
...
...
Titanium.Web.Proxy/Models/EndPoint.cs
View file @
70c107a4
...
...
@@ -53,7 +53,6 @@ namespace Titanium.Web.Proxy.Models
public
bool
IpV6Enabled
=>
Equals
(
IpAddress
,
IPAddress
.
IPv6Any
)
||
Equals
(
IpAddress
,
IPAddress
.
IPv6Loopback
)
||
Equals
(
IpAddress
,
IPAddress
.
IPv6None
);
}
/// <summary>
...
...
@@ -120,11 +119,14 @@ namespace Titanium.Web.Proxy.Models
/// <param name="ipAddress"></param>
/// <param name="port"></param>
/// <param name="enableSsl"></param>
public
ExplicitProxyEndPoint
(
IPAddress
ipAddress
,
int
port
,
bool
enableSsl
)
:
base
(
ipAddress
,
port
,
enableSsl
)
public
ExplicitProxyEndPoint
(
IPAddress
ipAddress
,
int
port
,
bool
enableSsl
)
:
base
(
ipAddress
,
port
,
enableSsl
)
{
//init to well known HTTPS ports
RemoteHttpsPorts
=
new
List
<
int
>
{
443
,
8443
};
RemoteHttpsPorts
=
new
List
<
int
>
{
443
,
8443
};
}
}
...
...
@@ -146,8 +148,7 @@ namespace Titanium.Web.Proxy.Models
/// <param name="ipAddress"></param>
/// <param name="port"></param>
/// <param name="enableSsl"></param>
public
TransparentProxyEndPoint
(
IPAddress
ipAddress
,
int
port
,
bool
enableSsl
)
:
base
(
ipAddress
,
port
,
enableSsl
)
public
TransparentProxyEndPoint
(
IPAddress
ipAddress
,
int
port
,
bool
enableSsl
)
:
base
(
ipAddress
,
port
,
enableSsl
)
{
GenericCertificateName
=
"localhost"
;
}
...
...
Titanium.Web.Proxy/Network/Certificate/BCCertificateMaker.cs
View file @
70c107a4
...
...
@@ -81,14 +81,10 @@ namespace Titanium.Web.Proxy.Network.Certificate
if
(
hostName
!=
null
)
{
//add subject alternative names
var
subjectAlternativeNames
=
new
Asn1Encodable
[]
{
new
GeneralName
(
GeneralName
.
DnsName
,
hostName
),
};
var
subjectAlternativeNames
=
new
Asn1Encodable
[]
{
new
GeneralName
(
GeneralName
.
DnsName
,
hostName
),
};
var
subjectAlternativeNamesExtension
=
new
DerSequence
(
subjectAlternativeNames
);
certificateGenerator
.
AddExtension
(
X509Extensions
.
SubjectAlternativeName
.
Id
,
false
,
subjectAlternativeNamesExtension
);
certificateGenerator
.
AddExtension
(
X509Extensions
.
SubjectAlternativeName
.
Id
,
false
,
subjectAlternativeNamesExtension
);
}
// Subject Public Key
var
keyGenerationParameters
=
new
KeyGenerationParameters
(
secureRandom
,
keyStrength
);
...
...
@@ -118,7 +114,8 @@ namespace Titanium.Web.Proxy.Network.Certificate
}
var
rsa
=
RsaPrivateKeyStructure
.
GetInstance
(
seq
);
var
rsaparams
=
new
RsaPrivateCrtKeyParameters
(
rsa
.
Modulus
,
rsa
.
PublicExponent
,
rsa
.
PrivateExponent
,
rsa
.
Prime1
,
rsa
.
Prime2
,
rsa
.
Exponent1
,
rsa
.
Exponent2
,
rsa
.
Coefficient
);
var
rsaparams
=
new
RsaPrivateCrtKeyParameters
(
rsa
.
Modulus
,
rsa
.
PublicExponent
,
rsa
.
PrivateExponent
,
rsa
.
Prime1
,
rsa
.
Prime2
,
rsa
.
Exponent1
,
rsa
.
Exponent2
,
rsa
.
Coefficient
);
// Set private key onto certificate instance
x509Certificate
.
PrivateKey
=
DotNetUtilities
.
ToRSA
(
rsaparams
);
...
...
@@ -138,9 +135,8 @@ namespace Titanium.Web.Proxy.Network.Certificate
/// <param name="signingCertificate">The signing certificate.</param>
/// <returns>X509Certificate2 instance.</returns>
/// <exception cref="System.ArgumentException">You must specify a Signing Certificate if and only if you are not creating a root.</exception>
private
X509Certificate2
MakeCertificateInternal
(
bool
isRoot
,
string
hostName
,
string
subjectName
,
DateTime
validFrom
,
DateTime
validTo
,
X509Certificate2
signingCertificate
)
private
X509Certificate2
MakeCertificateInternal
(
bool
isRoot
,
string
hostName
,
string
subjectName
,
DateTime
validFrom
,
DateTime
validTo
,
X509Certificate2
signingCertificate
)
{
if
(
isRoot
!=
(
null
==
signingCertificate
))
{
...
...
@@ -149,7 +145,8 @@ namespace Titanium.Web.Proxy.Network.Certificate
return
isRoot
?
GenerateCertificate
(
null
,
subjectName
,
subjectName
,
validFrom
,
validTo
)
:
GenerateCertificate
(
hostName
,
subjectName
,
signingCertificate
.
Subject
,
validFrom
,
validTo
,
issuerPrivateKey
:
DotNetUtilities
.
GetKeyPair
(
signingCertificate
.
PrivateKey
).
Private
);
:
GenerateCertificate
(
hostName
,
subjectName
,
signingCertificate
.
Subject
,
validFrom
,
validTo
,
issuerPrivateKey
:
DotNetUtilities
.
GetKeyPair
(
signingCertificate
.
PrivateKey
).
Private
);
}
/// <summary>
...
...
@@ -187,7 +184,8 @@ namespace Titanium.Web.Proxy.Network.Certificate
return
certificate
;
}
return
MakeCertificateInternal
(
isRoot
,
subject
,
$"CN=
{
subject
}
"
,
DateTime
.
UtcNow
.
AddDays
(-
certificateGraceDays
),
DateTime
.
UtcNow
.
AddDays
(
certificateValidDays
),
isRoot
?
null
:
signingCert
);
return
MakeCertificateInternal
(
isRoot
,
subject
,
$"CN=
{
subject
}
"
,
DateTime
.
UtcNow
.
AddDays
(-
certificateGraceDays
),
DateTime
.
UtcNow
.
AddDays
(
certificateValidDays
),
isRoot
?
null
:
signingCert
);
}
}
}
Titanium.Web.Proxy/Network/Certificate/WinCertificateMaker.cs
View file @
70c107a4
...
...
@@ -239,8 +239,6 @@ namespace Titanium.Web.Proxy.Network.Certificate
typeX509Enrollment
.
InvokeMember
(
"CertificateFriendlyName"
,
BindingFlags
.
PutDispProperty
,
null
,
x509Enrollment
,
typeValue
);
}
var
members
=
typeX509Enrollment
.
GetMembers
();
typeValue
[
0
]
=
0
;
var
createCertRequest
=
typeX509Enrollment
.
InvokeMember
(
"CreateRequest"
,
BindingFlags
.
InvokeMethod
,
null
,
x509Enrollment
,
typeValue
);
...
...
@@ -251,7 +249,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
try
{
var
empty
=
(
string
)
typeX509Enrollment
.
InvokeMember
(
"CreatePFX"
,
BindingFlags
.
InvokeMethod
,
null
,
x509Enrollment
,
typeValue
);
string
empty
=
(
string
)
typeX509Enrollment
.
InvokeMember
(
"CreatePFX"
,
BindingFlags
.
InvokeMethod
,
null
,
x509Enrollment
,
typeValue
);
return
new
X509Certificate2
(
Convert
.
FromBase64String
(
empty
),
string
.
Empty
,
X509KeyStorageFlags
.
Exportable
);
}
catch
(
Exception
)
...
...
@@ -281,15 +279,15 @@ namespace Titanium.Web.Proxy.Network.Certificate
}
//Subject
var
fullSubject
=
$"CN=
{
sSubjectCN
}
"
;
string
fullSubject
=
$"CN=
{
sSubjectCN
}
"
;
//Sig Algo
var
HashAlgo
=
"SHA256"
;
string
HashAlgo
=
"SHA256"
;
//Grace Days
var
GraceDays
=
-
366
;
int
GraceDays
=
-
366
;
//ValiDays
var
ValidDays
=
1825
;
int
ValidDays
=
1825
;
//KeyLength
var
keyLength
=
2048
;
int
keyLength
=
2048
;
var
graceTime
=
DateTime
.
Now
.
AddDays
(
GraceDays
);
var
now
=
DateTime
.
Now
;
...
...
Titanium.Web.Proxy/Network/CertificateManager.cs
View file @
70c107a4
...
...
@@ -52,9 +52,7 @@ namespace Titanium.Web.Proxy.Network
if
(
certEngine
==
null
)
{
certEngine
=
engine
==
CertificateEngine
.
BouncyCastle
?
(
ICertificateMaker
)
new
BCCertificateMaker
()
:
new
WinCertificateMaker
();
certEngine
=
engine
==
CertificateEngine
.
BouncyCastle
?
(
ICertificateMaker
)
new
BCCertificateMaker
()
:
new
WinCertificateMaker
();
}
}
}
...
...
@@ -134,7 +132,7 @@ namespace Titanium.Web.Proxy.Network
private
string
GetRootCertificatePath
()
{
var
assemblyLocation
=
Assembly
.
GetExecutingAssembly
().
Location
;
string
assemblyLocation
=
Assembly
.
GetExecutingAssembly
().
Location
;
// dynamically loaded assemblies returns string.Empty location
if
(
assemblyLocation
==
string
.
Empty
)
...
...
@@ -142,16 +140,18 @@ namespace Titanium.Web.Proxy.Network
assemblyLocation
=
Assembly
.
GetEntryAssembly
().
Location
;
}
var
path
=
Path
.
GetDirectoryName
(
assemblyLocation
);
if
(
null
==
path
)
throw
new
NullReferenceException
();
var
fileName
=
Path
.
Combine
(
path
,
"rootCert.pfx"
);
string
path
=
Path
.
GetDirectoryName
(
assemblyLocation
);
if
(
null
==
path
)
throw
new
NullReferenceException
();
string
fileName
=
Path
.
Combine
(
path
,
"rootCert.pfx"
);
return
fileName
;
}
private
X509Certificate2
LoadRootCertificate
()
{
var
fileName
=
GetRootCertificatePath
();
if
(!
File
.
Exists
(
fileName
))
return
null
;
string
fileName
=
GetRootCertificatePath
();
if
(!
File
.
Exists
(
fileName
))
return
null
;
try
{
return
new
X509Certificate2
(
fileName
,
string
.
Empty
,
X509KeyStorageFlags
.
Exportable
);
...
...
@@ -195,7 +195,7 @@ namespace Titanium.Web.Proxy.Network
{
try
{
var
fileName
=
GetRootCertificatePath
();
string
fileName
=
GetRootCertificatePath
();
File
.
WriteAllBytes
(
fileName
,
RootCertificate
.
Export
(
X509ContentType
.
Pkcs12
));
}
catch
(
Exception
e
)
...
...
@@ -231,7 +231,7 @@ namespace Titanium.Web.Proxy.Network
return
false
;
}
var
fileName
=
Path
.
GetTempFileName
();
string
fileName
=
Path
.
GetTempFileName
();
File
.
WriteAllBytes
(
fileName
,
RootCertificate
.
Export
(
X509ContentType
.
Pkcs12
));
var
info
=
new
ProcessStartInfo
...
...
@@ -340,7 +340,7 @@ namespace Titanium.Web.Proxy.Network
private
X509Certificate2Collection
FindCertificates
(
StoreName
storeName
,
StoreLocation
storeLocation
,
string
findValue
)
{
X509Store
x509Store
=
new
X509Store
(
storeName
,
storeLocation
);
var
x509Store
=
new
X509Store
(
storeName
,
storeLocation
);
try
{
x509Store
.
Open
(
OpenFlags
.
OpenExistingOnly
);
...
...
@@ -351,7 +351,7 @@ namespace Titanium.Web.Proxy.Network
x509Store
.
Close
();
}
}
/// <summary>
/// Create an SSL certificate
/// </summary>
...
...
@@ -387,7 +387,10 @@ namespace Titanium.Web.Proxy.Network
}
if
(
certificate
!=
null
&&
!
certificateCache
.
ContainsKey
(
certificateName
))
{
certificateCache
.
Add
(
certificateName
,
new
CachedCertificate
{
Certificate
=
certificate
});
certificateCache
.
Add
(
certificateName
,
new
CachedCertificate
{
Certificate
=
certificate
});
}
}
else
...
...
@@ -422,9 +425,7 @@ namespace Titanium.Web.Proxy.Network
{
var
cutOff
=
DateTime
.
Now
.
AddMinutes
(-
1
*
certificateCacheTimeOutMinutes
);
var
outdated
=
certificateCache
.
Where
(
x
=>
x
.
Value
.
LastAccess
<
cutOff
)
.
ToList
();
var
outdated
=
certificateCache
.
Where
(
x
=>
x
.
Value
.
LastAccess
<
cutOff
).
ToList
();
foreach
(
var
cache
in
outdated
)
certificateCache
.
Remove
(
cache
.
Key
);
...
...
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
View file @
70c107a4
...
...
@@ -29,22 +29,17 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <param name="externalHttpProxy"></param>
/// <param name="externalHttpsProxy"></param>
/// <returns></returns>
internal
async
Task
<
TcpConnection
>
CreateClient
(
ProxyServer
server
,
string
remoteHostName
,
int
remotePort
,
Version
httpVersion
,
bool
isHttps
,
internal
async
Task
<
TcpConnection
>
CreateClient
(
ProxyServer
server
,
string
remoteHostName
,
int
remotePort
,
Version
httpVersion
,
bool
isHttps
,
ExternalProxy
externalHttpProxy
,
ExternalProxy
externalHttpsProxy
)
{
bool
useHttpProxy
=
false
;
bool
useHttpProxy
=
false
;
//check if external proxy is set for HTTP
if
(!
isHttps
&&
externalHttpProxy
!=
null
&&
!(
externalHttpProxy
.
HostName
==
remoteHostName
&&
externalHttpProxy
.
Port
==
remotePort
))
if
(!
isHttps
&&
externalHttpProxy
!=
null
&&
!(
externalHttpProxy
.
HostName
==
remoteHostName
&&
externalHttpProxy
.
Port
==
remotePort
))
{
useHttpProxy
=
true
;
//check if we need to ByPass
if
(
externalHttpProxy
.
BypassLocalhost
&&
NetworkHelper
.
IsLocalIpAddress
(
remoteHostName
))
if
(
externalHttpProxy
.
BypassLocalhost
&&
NetworkHelper
.
IsLocalIpAddress
(
remoteHostName
))
{
useHttpProxy
=
false
;
}
...
...
@@ -52,15 +47,12 @@ namespace Titanium.Web.Proxy.Network.Tcp
bool
useHttpsProxy
=
false
;
//check if external proxy is set for HTTPS
if
(
isHttps
&&
externalHttpsProxy
!=
null
&&
!(
externalHttpsProxy
.
HostName
==
remoteHostName
&&
externalHttpsProxy
.
Port
==
remotePort
))
if
(
isHttps
&&
externalHttpsProxy
!=
null
&&
!(
externalHttpsProxy
.
HostName
==
remoteHostName
&&
externalHttpsProxy
.
Port
==
remotePort
))
{
useHttpsProxy
=
true
;
//check if we need to ByPass
if
(
externalHttpsProxy
.
BypassLocalhost
&&
NetworkHelper
.
IsLocalIpAddress
(
remoteHostName
))
if
(
externalHttpsProxy
.
BypassLocalhost
&&
NetworkHelper
.
IsLocalIpAddress
(
remoteHostName
))
{
useHttpsProxy
=
false
;
}
...
...
@@ -80,7 +72,10 @@ namespace Titanium.Web.Proxy.Network.Tcp
await
client
.
ConnectAsync
(
externalHttpsProxy
.
HostName
,
externalHttpsProxy
.
Port
);
stream
=
new
CustomBufferedStream
(
client
.
GetStream
(),
server
.
BufferSize
);
using
(
var
writer
=
new
StreamWriter
(
stream
,
Encoding
.
ASCII
,
server
.
BufferSize
,
true
)
{
NewLine
=
ProxyConstants
.
NewLine
})
using
(
var
writer
=
new
StreamWriter
(
stream
,
Encoding
.
ASCII
,
server
.
BufferSize
,
true
)
{
NewLine
=
ProxyConstants
.
NewLine
})
{
await
writer
.
WriteLineAsync
(
$"CONNECT
{
remoteHostName
}
:
{
remotePort
}
HTTP/
{
httpVersion
}
"
);
await
writer
.
WriteLineAsync
(
$"Host:
{
remoteHostName
}
:
{
remotePort
}
"
);
...
...
@@ -89,7 +84,9 @@ namespace Titanium.Web.Proxy.Network.Tcp
if
(!
string
.
IsNullOrEmpty
(
externalHttpsProxy
.
UserName
)
&&
externalHttpsProxy
.
Password
!=
null
)
{
await
writer
.
WriteLineAsync
(
"Proxy-Connection: keep-alive"
);
await
writer
.
WriteLineAsync
(
"Proxy-Authorization"
+
": Basic "
+
Convert
.
ToBase64String
(
Encoding
.
UTF8
.
GetBytes
(
externalHttpsProxy
.
UserName
+
":"
+
externalHttpsProxy
.
Password
)));
await
writer
.
WriteLineAsync
(
"Proxy-Authorization"
+
": Basic "
+
Convert
.
ToBase64String
(
Encoding
.
UTF8
.
GetBytes
(
externalHttpsProxy
.
UserName
+
":"
+
externalHttpsProxy
.
Password
)));
}
await
writer
.
WriteLineAsync
();
await
writer
.
FlushAsync
();
...
...
@@ -98,7 +95,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
using
(
var
reader
=
new
CustomBinaryReader
(
stream
,
server
.
BufferSize
))
{
var
result
=
await
reader
.
ReadLineAsync
();
string
result
=
await
reader
.
ReadLineAsync
();
if
(!
new
[]
{
"200 OK"
,
"connection established"
}.
Any
(
s
=>
result
.
ContainsIgnoreCase
(
s
)))
{
...
...
Titanium.Web.Proxy/Network/Tcp/TcpTable.cs
View file @
70c107a4
...
...
@@ -11,21 +11,19 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// </seealso>
internal
class
TcpTable
:
IEnumerable
<
TcpRow
>
{
private
readonly
IEnumerable
<
TcpRow
>
tcpRows
;
/// <summary>
/// Initializes a new instance of the <see cref="TcpTable"/> class.
/// </summary>
/// <param name="tcpRows">TcpRow collection to initialize with.</param>
internal
TcpTable
(
IEnumerable
<
TcpRow
>
tcpRows
)
{
this
.
t
cpRows
=
tcpRows
;
this
.
T
cpRows
=
tcpRows
;
}
/// <summary>
/// Gets the TCP rows.
/// </summary>
internal
IEnumerable
<
TcpRow
>
TcpRows
=>
tcpRows
;
internal
IEnumerable
<
TcpRow
>
TcpRows
{
get
;
}
/// <summary>
/// Returns an enumerator that iterates through the collection.
...
...
@@ -33,7 +31,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
/// <returns>An enumerator that can be used to iterate through the collection.</returns>
public
IEnumerator
<
TcpRow
>
GetEnumerator
()
{
return
t
cpRows
.
GetEnumerator
();
return
T
cpRows
.
GetEnumerator
();
}
/// <summary>
...
...
Titanium.Web.Proxy/Network/WinAuth/Security/Common.cs
View file @
70c107a4
namespace
Titanium.Web.Proxy.Network.WinAuth.Security
{
using
System
;
using
System.Runtime.InteropServices
;
using
System
;
using
System.Runtime.InteropServices
;
namespace
Titanium.Web.Proxy.Network.WinAuth.Security
{
internal
class
Common
{
#
region
Private
constants
private
const
int
ISC_REQ_REPLAY_DETECT
=
0x00000004
;
private
const
int
ISC_REQ_SEQUENCE_DETECT
=
0x00000008
;
private
const
int
ISC_REQ_CONFIDENTIALITY
=
0x00000010
;
private
const
int
ISC_REQ_CONNECTION
=
0x00000800
;
#
endregion
internal
static
uint
NewContextAttributes
=
0
;
internal
static
Common
.
SecurityInteger
NewLifeTime
=
new
SecurityInteger
(
0
);
internal
static
SecurityInteger
NewLifeTime
=
new
SecurityInteger
(
0
);
#
region
internal
constants
internal
const
int
StandardContextAttributes
=
ISC_REQ_CONFIDENTIALITY
|
ISC_REQ_REPLAY_DETECT
|
ISC_REQ_SEQUENCE_DETECT
|
ISC_REQ_CONNECTION
;
internal
const
int
SecurityNativeDataRepresentation
=
0x10
;
internal
const
int
MaximumTokenSize
=
12288
;
internal
const
int
SecurityCredentialsOutbound
=
2
;
internal
const
int
SuccessfulResult
=
0
;
internal
const
int
IntermediateResult
=
0x90312
;
#
endregion
#
region
internal
enumerations
internal
enum
SecurityBufferType
{
SECBUFFER_VERSION
=
0
,
...
...
@@ -34,26 +39,35 @@
}
[
Flags
]
internal
enum
NtlmFlags
:
int
internal
enum
NtlmFlags
{
// The client sets this flag to indicate that it supports Unicode strings.
NegotiateUnicode
=
0x00000001
,
// This is set to indicate that the client supports OEM strings.
NegotiateOem
=
0x00000002
,
// This requests that the server send the authentication target with the Type 2 reply.
RequestTarget
=
0x00000004
,
// Indicates that NTLM authentication is supported.
NegotiateNtlm
=
0x00000200
,
// When set, the client will send with the message the name of the domain in which the workstation has membership.
NegotiateDomainSupplied
=
0x00001000
,
// Indicates that the client is sending its workstation name with the message.
NegotiateWorkstationSupplied
=
0x00002000
,
// Indicates that communication between the client and server after authentication should carry a "dummy" signature.
NegotiateAlwaysSign
=
0x00008000
,
// Indicates that this client supports the NTLM2 signing and sealing scheme; if negotiated, this can also affect the response calculations.
NegotiateNtlm2Key
=
0x00080000
,
// Indicates that this client supports strong (128-bit) encryption.
Negotiate128
=
0x20000000
,
// Indicates that this client supports medium (56-bit) encryption.
Negotiate56
=
(
unchecked
((
int
)
0x80000000
))
}
...
...
@@ -74,9 +88,11 @@
/* Use NTLMv2 only. */
NTLMv2_only
,
}
#
endregion
#
region
internal
structures
[
StructLayout
(
LayoutKind
.
Sequential
)]
internal
struct
SecurityHandle
{
...
...
@@ -102,6 +118,7 @@
{
internal
uint
LowPart
;
internal
int
HighPart
;
internal
SecurityInteger
(
int
dummy
)
{
LowPart
=
0
;
...
...
@@ -152,7 +169,6 @@
[
StructLayout
(
LayoutKind
.
Sequential
)]
internal
struct
SecurityBufferDesciption
:
IDisposable
{
internal
int
ulVersion
;
internal
int
cBuffers
;
internal
IntPtr
pBuffers
;
//Point to SecBuffer
...
...
@@ -161,18 +177,18 @@
{
ulVersion
=
(
int
)
SecurityBufferType
.
SECBUFFER_VERSION
;
cBuffers
=
1
;
Common
.
SecurityBuffer
ThisSecBuffer
=
new
Common
.
SecurityBuffer
(
bufferSize
);
pBuffers
=
Marshal
.
AllocHGlobal
(
Marshal
.
SizeOf
(
T
hisSecBuffer
));
Marshal
.
StructureToPtr
(
T
hisSecBuffer
,
pBuffers
,
false
);
var
thisSecBuffer
=
new
SecurityBuffer
(
bufferSize
);
pBuffers
=
Marshal
.
AllocHGlobal
(
Marshal
.
SizeOf
(
t
hisSecBuffer
));
Marshal
.
StructureToPtr
(
t
hisSecBuffer
,
pBuffers
,
false
);
}
internal
SecurityBufferDesciption
(
byte
[]
secBufferBytes
)
{
ulVersion
=
(
int
)
SecurityBufferType
.
SECBUFFER_VERSION
;
cBuffers
=
1
;
Common
.
SecurityBuffer
ThisSecBuffer
=
new
Common
.
SecurityBuffer
(
secBufferBytes
);
pBuffers
=
Marshal
.
AllocHGlobal
(
Marshal
.
SizeOf
(
T
hisSecBuffer
));
Marshal
.
StructureToPtr
(
T
hisSecBuffer
,
pBuffers
,
false
);
var
thisSecBuffer
=
new
SecurityBuffer
(
secBufferBytes
);
pBuffers
=
Marshal
.
AllocHGlobal
(
Marshal
.
SizeOf
(
t
hisSecBuffer
));
Marshal
.
StructureToPtr
(
t
hisSecBuffer
,
pBuffers
,
false
);
}
public
void
Dispose
()
...
...
@@ -181,12 +197,12 @@
{
if
(
cBuffers
==
1
)
{
Common
.
SecurityBuffer
ThisSecBuffer
=
(
Common
.
SecurityBuffer
)
Marshal
.
PtrToStructure
(
pBuffers
,
typeof
(
Common
.
SecurityBuffer
));
T
hisSecBuffer
.
Dispose
();
var
thisSecBuffer
=
(
SecurityBuffer
)
Marshal
.
PtrToStructure
(
pBuffers
,
typeof
(
SecurityBuffer
));
t
hisSecBuffer
.
Dispose
();
}
else
{
for
(
int
Index
=
0
;
Index
<
cBuffers
;
I
ndex
++)
for
(
int
index
=
0
;
index
<
cBuffers
;
i
ndex
++)
{
//The bits were written out the following order:
//int cbBuffer;
...
...
@@ -194,9 +210,9 @@
//pvBuffer;
//What we need to do here is to grab a hold of the pvBuffer allocate by the individual
//SecBuffer and release it...
int
CurrentOffset
=
I
ndex
*
Marshal
.
SizeOf
(
typeof
(
Buffer
));
IntPtr
SecBufferpvBuffer
=
Marshal
.
ReadIntPtr
(
pBuffers
,
C
urrentOffset
+
Marshal
.
SizeOf
(
typeof
(
int
))
+
Marshal
.
SizeOf
(
typeof
(
int
)));
Marshal
.
FreeHGlobal
(
S
ecBufferpvBuffer
);
int
currentOffset
=
i
ndex
*
Marshal
.
SizeOf
(
typeof
(
Buffer
));
var
secBufferpvBuffer
=
Marshal
.
ReadIntPtr
(
pBuffers
,
c
urrentOffset
+
Marshal
.
SizeOf
(
typeof
(
int
))
+
Marshal
.
SizeOf
(
typeof
(
int
)));
Marshal
.
FreeHGlobal
(
s
ecBufferpvBuffer
);
}
}
...
...
@@ -207,7 +223,7 @@
internal
byte
[]
GetBytes
()
{
byte
[]
B
uffer
=
null
;
byte
[]
b
uffer
=
null
;
if
(
pBuffers
==
IntPtr
.
Zero
)
{
...
...
@@ -216,32 +232,32 @@
if
(
cBuffers
==
1
)
{
Common
.
SecurityBuffer
ThisSecBuffer
=
(
Common
.
SecurityBuffer
)
Marshal
.
PtrToStructure
(
pBuffers
,
typeof
(
Common
.
SecurityBuffer
));
var
thisSecBuffer
=
(
SecurityBuffer
)
Marshal
.
PtrToStructure
(
pBuffers
,
typeof
(
SecurityBuffer
));
if
(
T
hisSecBuffer
.
cbBuffer
>
0
)
if
(
t
hisSecBuffer
.
cbBuffer
>
0
)
{
Buffer
=
new
byte
[
T
hisSecBuffer
.
cbBuffer
];
Marshal
.
Copy
(
ThisSecBuffer
.
pvBuffer
,
Buffer
,
0
,
T
hisSecBuffer
.
cbBuffer
);
buffer
=
new
byte
[
t
hisSecBuffer
.
cbBuffer
];
Marshal
.
Copy
(
thisSecBuffer
.
pvBuffer
,
buffer
,
0
,
t
hisSecBuffer
.
cbBuffer
);
}
}
else
{
int
B
ytesToAllocate
=
0
;
int
b
ytesToAllocate
=
0
;
for
(
int
Index
=
0
;
Index
<
cBuffers
;
I
ndex
++)
for
(
int
index
=
0
;
index
<
cBuffers
;
i
ndex
++)
{
//The bits were written out the following order:
//int cbBuffer;
//int BufferType;
//pvBuffer;
//What we need to do here calculate the total number of bytes we need to copy...
int
CurrentOffset
=
I
ndex
*
Marshal
.
SizeOf
(
typeof
(
Buffer
));
BytesToAllocate
+=
Marshal
.
ReadInt32
(
pBuffers
,
C
urrentOffset
);
int
currentOffset
=
i
ndex
*
Marshal
.
SizeOf
(
typeof
(
Buffer
));
bytesToAllocate
+=
Marshal
.
ReadInt32
(
pBuffers
,
c
urrentOffset
);
}
Buffer
=
new
byte
[
B
ytesToAllocate
];
buffer
=
new
byte
[
b
ytesToAllocate
];
for
(
int
Index
=
0
,
BufferIndex
=
0
;
Index
<
cBuffers
;
I
ndex
++)
for
(
int
index
=
0
,
bufferIndex
=
0
;
index
<
cBuffers
;
i
ndex
++)
{
//The bits were written out the following order:
//int cbBuffer;
...
...
@@ -249,17 +265,18 @@
//pvBuffer;
//Now iterate over the individual buffers and put them together into a
//byte array...
int
CurrentOffset
=
I
ndex
*
Marshal
.
SizeOf
(
typeof
(
Buffer
));
int
BytesToCopy
=
Marshal
.
ReadInt32
(
pBuffers
,
C
urrentOffset
);
IntPtr
SecBufferpvBuffer
=
Marshal
.
ReadIntPtr
(
pBuffers
,
C
urrentOffset
+
Marshal
.
SizeOf
(
typeof
(
int
))
+
Marshal
.
SizeOf
(
typeof
(
int
)));
Marshal
.
Copy
(
SecBufferpvBuffer
,
Buffer
,
BufferIndex
,
B
ytesToCopy
);
BufferIndex
+=
B
ytesToCopy
;
int
currentOffset
=
i
ndex
*
Marshal
.
SizeOf
(
typeof
(
Buffer
));
int
bytesToCopy
=
Marshal
.
ReadInt32
(
pBuffers
,
c
urrentOffset
);
var
secBufferpvBuffer
=
Marshal
.
ReadIntPtr
(
pBuffers
,
c
urrentOffset
+
Marshal
.
SizeOf
(
typeof
(
int
))
+
Marshal
.
SizeOf
(
typeof
(
int
)));
Marshal
.
Copy
(
secBufferpvBuffer
,
buffer
,
bufferIndex
,
b
ytesToCopy
);
bufferIndex
+=
b
ytesToCopy
;
}
}
return
(
B
uffer
);
return
(
b
uffer
);
}
}
#
endregion
}
}
Titanium.Web.Proxy/Network/WinAuth/Security/LittleEndian.cs
View file @
70c107a4
...
...
@@ -27,231 +27,226 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using
System
;
namespace
Titanium.Web.Proxy.Network.WinAuth.Security
{
using
System
;
internal
sealed
class
LittleEndian
{
private
LittleEndian
()
{
}
private
static
unsafe
byte
[]
GetUShortBytes
(
byte
*
bytes
)
{
if
(
BitConverter
.
IsLittleEndian
)
{
return
new
[]
{
bytes
[
0
],
bytes
[
1
]
};
}
internal
sealed
class
LittleEndian
{
private
LittleEndian
()
{
}
return
new
[]
{
bytes
[
1
],
bytes
[
0
]
};
}
unsafe
private
static
byte
[]
GetUShortBytes
(
byte
*
bytes
)
{
private
static
unsafe
byte
[]
GetUIntBytes
(
byte
*
bytes
)
{
if
(
BitConverter
.
IsLittleEndian
)
{
return
new
byte
[]
{
bytes
[
0
],
bytes
[
1
]
};
return
new
[]
{
bytes
[
0
],
bytes
[
1
],
bytes
[
2
],
bytes
[
3
]
};
}
else
return
new
[]
{
bytes
[
3
],
bytes
[
2
],
bytes
[
1
],
bytes
[
0
]
};
}
private
static
unsafe
byte
[]
GetULongBytes
(
byte
*
bytes
)
{
if
(
BitConverter
.
IsLittleEndian
)
{
return
new
byte
[]
{
bytes
[
1
],
bytes
[
0
]
};
return
new
[]
{
bytes
[
0
],
bytes
[
1
],
bytes
[
2
],
bytes
[
3
],
bytes
[
4
],
bytes
[
5
],
bytes
[
6
],
bytes
[
7
]
};
}
}
unsafe
private
static
byte
[]
GetUIntBytes
(
byte
*
bytes
)
{
return
new
[]
{
bytes
[
7
],
bytes
[
6
],
bytes
[
5
],
bytes
[
4
],
bytes
[
3
],
bytes
[
2
],
bytes
[
1
],
bytes
[
0
]
};
}
internal
static
byte
[]
GetBytes
(
bool
value
)
{
return
new
[]
{
value
?
(
byte
)
1
:
(
byte
)
0
};
}
internal
static
unsafe
byte
[]
GetBytes
(
char
value
)
{
return
GetUShortBytes
((
byte
*)&
value
);
}
internal
static
unsafe
byte
[]
GetBytes
(
short
value
)
{
return
GetUShortBytes
((
byte
*)&
value
);
}
internal
static
unsafe
byte
[]
GetBytes
(
int
value
)
{
return
GetUIntBytes
((
byte
*)&
value
);
}
internal
static
unsafe
byte
[]
GetBytes
(
long
value
)
{
return
GetULongBytes
((
byte
*)&
value
);
}
internal
static
unsafe
byte
[]
GetBytes
(
ushort
value
)
{
return
GetUShortBytes
((
byte
*)&
value
);
}
internal
static
unsafe
byte
[]
GetBytes
(
uint
value
)
{
return
GetUIntBytes
((
byte
*)&
value
);
}
internal
static
unsafe
byte
[]
GetBytes
(
ulong
value
)
{
return
GetULongBytes
((
byte
*)&
value
);
}
internal
static
unsafe
byte
[]
GetBytes
(
float
value
)
{
return
GetUIntBytes
((
byte
*)&
value
);
}
internal
static
unsafe
byte
[]
GetBytes
(
double
value
)
{
return
GetULongBytes
((
byte
*)&
value
);
}
private
static
unsafe
void
UShortFromBytes
(
byte
*
dst
,
byte
[]
src
,
int
startIndex
)
{
if
(
BitConverter
.
IsLittleEndian
)
{
return
new
byte
[]
{
bytes
[
0
],
bytes
[
1
],
bytes
[
2
],
bytes
[
3
]
};
dst
[
0
]
=
src
[
startIndex
];
dst
[
1
]
=
src
[
startIndex
+
1
];
}
else
{
return
new
byte
[]
{
bytes
[
3
],
bytes
[
2
],
bytes
[
1
],
bytes
[
0
]
};
dst
[
0
]
=
src
[
startIndex
+
1
];
dst
[
1
]
=
src
[
startIndex
];
}
}
}
unsafe
private
static
byte
[]
GetULongBytes
(
byte
*
bytes
)
{
private
static
unsafe
void
UIntFromBytes
(
byte
*
dst
,
byte
[]
src
,
int
startIndex
)
{
if
(
BitConverter
.
IsLittleEndian
)
{
return
new
byte
[]
{
bytes
[
0
],
bytes
[
1
],
bytes
[
2
],
bytes
[
3
],
bytes
[
4
],
bytes
[
5
],
bytes
[
6
],
bytes
[
7
]
};
dst
[
0
]
=
src
[
startIndex
];
dst
[
1
]
=
src
[
startIndex
+
1
];
dst
[
2
]
=
src
[
startIndex
+
2
];
dst
[
3
]
=
src
[
startIndex
+
3
];
}
else
{
return
new
byte
[]
{
bytes
[
7
],
bytes
[
6
],
bytes
[
5
],
bytes
[
4
],
bytes
[
3
],
bytes
[
2
],
bytes
[
1
],
bytes
[
0
]
};
dst
[
0
]
=
src
[
startIndex
+
3
];
dst
[
1
]
=
src
[
startIndex
+
2
];
dst
[
2
]
=
src
[
startIndex
+
1
];
dst
[
3
]
=
src
[
startIndex
];
}
}
unsafe
internal
static
byte
[]
GetBytes
(
bool
value
)
{
return
new
byte
[]
{
value
?
(
byte
)
1
:
(
byte
)
0
};
}
unsafe
internal
static
byte
[]
GetBytes
(
char
value
)
{
return
GetUShortBytes
((
byte
*)
&
value
);
}
unsafe
internal
static
byte
[]
GetBytes
(
short
value
)
{
return
GetUShortBytes
((
byte
*)
&
value
);
}
unsafe
internal
static
byte
[]
GetBytes
(
int
value
)
{
return
GetUIntBytes
((
byte
*)
&
value
);
}
unsafe
internal
static
byte
[]
GetBytes
(
long
value
)
{
return
GetULongBytes
((
byte
*)
&
value
);
}
unsafe
internal
static
byte
[]
GetBytes
(
ushort
value
)
{
return
GetUShortBytes
((
byte
*)
&
value
);
}
unsafe
internal
static
byte
[]
GetBytes
(
uint
value
)
{
return
GetUIntBytes
((
byte
*)
&
value
);
}
unsafe
internal
static
byte
[]
GetBytes
(
ulong
value
)
{
return
GetULongBytes
((
byte
*)
&
value
);
}
unsafe
internal
static
byte
[]
GetBytes
(
float
value
)
{
return
GetUIntBytes
((
byte
*)
&
value
);
}
unsafe
internal
static
byte
[]
GetBytes
(
double
value
)
{
return
GetULongBytes
((
byte
*)
&
value
);
}
unsafe
private
static
void
UShortFromBytes
(
byte
*
dst
,
byte
[]
src
,
int
startIndex
)
{
if
(
BitConverter
.
IsLittleEndian
)
{
dst
[
0
]
=
src
[
startIndex
];
dst
[
1
]
=
src
[
startIndex
+
1
];
}
else
{
dst
[
0
]
=
src
[
startIndex
+
1
];
dst
[
1
]
=
src
[
startIndex
];
}
}
unsafe
private
static
void
UIntFromBytes
(
byte
*
dst
,
byte
[]
src
,
int
startIndex
)
{
if
(
BitConverter
.
IsLittleEndian
)
}
private
static
unsafe
void
ULongFromBytes
(
byte
*
dst
,
byte
[]
src
,
int
startIndex
)
{
if
(
BitConverter
.
IsLittleEndian
)
{
dst
[
0
]
=
src
[
startIndex
];
dst
[
1
]
=
src
[
startIndex
+
1
];
dst
[
2
]
=
src
[
startIndex
+
2
];
dst
[
3
]
=
src
[
startIndex
+
3
];
}
else
for
(
int
i
=
0
;
i
<
8
;
++
i
)
dst
[
i
]
=
src
[
startIndex
+
i
];
}
else
{
dst
[
0
]
=
src
[
startIndex
+
3
];
dst
[
1
]
=
src
[
startIndex
+
2
];
dst
[
2
]
=
src
[
startIndex
+
1
];
dst
[
3
]
=
src
[
startIndex
];
}
}
unsafe
private
static
void
ULongFromBytes
(
byte
*
dst
,
byte
[]
src
,
int
startIndex
)
{
if
(
BitConverter
.
IsLittleEndian
)
{
for
(
int
i
=
0
;
i
<
8
;
++
i
)
dst
[
i
]
=
src
[
startIndex
+
i
];
}
else
{
for
(
int
i
=
0
;
i
<
8
;
++
i
)
dst
[
i
]
=
src
[
startIndex
+
(
7
-
i
)];
}
}
for
(
int
i
=
0
;
i
<
8
;
++
i
)
dst
[
i
]
=
src
[
startIndex
+
(
7
-
i
)];
}
}
unsafe
internal
static
bool
ToBoolean
(
byte
[]
value
,
int
startIndex
)
{
return
value
[
startIndex
]
!=
0
;
}
internal
static
bool
ToBoolean
(
byte
[]
value
,
int
startIndex
)
{
return
value
[
startIndex
]
!=
0
;
}
unsafe
internal
static
char
ToChar
(
byte
[]
value
,
int
startIndex
)
{
char
ret
;
internal
static
unsafe
char
ToChar
(
byte
[]
value
,
int
startIndex
)
{
char
ret
;
UShortFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
UShortFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
return
ret
;
}
return
ret
;
}
unsafe
internal
static
short
ToInt16
(
byte
[]
value
,
int
startIndex
)
{
short
ret
;
internal
static
unsafe
short
ToInt16
(
byte
[]
value
,
int
startIndex
)
{
short
ret
;
UShortFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
UShortFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
return
ret
;
}
return
ret
;
}
unsafe
internal
static
int
ToInt32
(
byte
[]
value
,
int
startIndex
)
{
int
ret
;
internal
static
unsafe
int
ToInt32
(
byte
[]
value
,
int
startIndex
)
{
int
ret
;
UIntFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
UIntFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
return
ret
;
}
return
ret
;
}
unsafe
internal
static
long
ToInt64
(
byte
[]
value
,
int
startIndex
)
{
long
ret
;
internal
static
unsafe
long
ToInt64
(
byte
[]
value
,
int
startIndex
)
{
long
ret
;
ULongFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
ULongFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
return
ret
;
}
return
ret
;
}
unsafe
internal
static
ushort
ToUInt16
(
byte
[]
value
,
int
startIndex
)
{
ushort
ret
;
internal
static
unsafe
ushort
ToUInt16
(
byte
[]
value
,
int
startIndex
)
{
ushort
ret
;
UShortFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
UShortFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
return
ret
;
}
return
ret
;
}
unsafe
internal
static
uint
ToUInt32
(
byte
[]
value
,
int
startIndex
)
{
uint
ret
;
internal
static
unsafe
uint
ToUInt32
(
byte
[]
value
,
int
startIndex
)
{
uint
ret
;
UIntFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
UIntFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
return
ret
;
}
return
ret
;
}
unsafe
internal
static
ulong
ToUInt64
(
byte
[]
value
,
int
startIndex
)
{
ulong
ret
;
internal
static
unsafe
ulong
ToUInt64
(
byte
[]
value
,
int
startIndex
)
{
ulong
ret
;
ULongFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
ULongFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
return
ret
;
}
return
ret
;
}
unsafe
internal
static
float
ToSingle
(
byte
[]
value
,
int
startIndex
)
{
float
ret
;
internal
static
unsafe
float
ToSingle
(
byte
[]
value
,
int
startIndex
)
{
float
ret
;
UIntFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
UIntFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
return
ret
;
}
return
ret
;
}
unsafe
internal
static
double
ToDouble
(
byte
[]
value
,
int
startIndex
)
{
double
ret
;
internal
static
unsafe
double
ToDouble
(
byte
[]
value
,
int
startIndex
)
{
double
ret
;
ULongFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
ULongFromBytes
((
byte
*)
&
ret
,
value
,
startIndex
);
return
ret
;
}
}
return
ret
;
}
}
}
Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs
View file @
70c107a4
...
...
@@ -33,51 +33,38 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
namespace
Titanium.Web.Proxy.Network.WinAuth.Security
{
using
System
;
using
System.Text
;
using
System
;
using
System.Text
;
internal
class
Message
namespace
Titanium.Web.Proxy.Network.WinAuth.Security
{
internal
class
Message
{
static
private
byte
[]
header
=
{
0x4e
,
0x54
,
0x4c
,
0x4d
,
0x53
,
0x53
,
0x50
,
0x00
};
internal
Message
(
byte
[]
message
)
{
_type
=
3
;
Decode
(
message
);
}
/// <summary>
/// Domain name
/// </summary>
internal
string
Domain
private
static
readonly
byte
[]
header
=
{
0x4e
,
0x54
,
0x4c
,
0x4d
,
0x53
,
0x53
,
0x50
,
0x00
};
internal
Message
(
byte
[]
message
)
{
get
;
private
set
;
type
=
3
;
Decode
(
message
)
;
}
/// <summary>
/// Domain name
/// </summary>
internal
string
Domain
{
get
;
private
set
;
}
/// <summary>
/// Username
/// </summary>
internal
string
Username
{
get
;
private
set
;
}
internal
string
Username
{
get
;
private
set
;
}
private
int
_type
;
private
Common
.
NtlmFlags
_flags
;
private
readonly
int
type
;
internal
Common
.
NtlmFlags
Flags
{
get
{
return
_flags
;
}
set
{
_flags
=
value
;
}
}
internal
Common
.
NtlmFlags
Flags
{
get
;
set
;
}
// methods
private
void
Decode
(
byte
[]
message
)
{
// methods
private
void
Decode
(
byte
[]
message
)
{
//base.Decode (message);
if
(
message
==
null
)
...
...
@@ -95,11 +82,11 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
throw
new
ArgumentException
(
msg
,
"message"
);
}
if
(
LittleEndian
.
ToUInt16
(
message
,
56
)
!=
message
.
Length
)
if
(
LittleEndian
.
ToUInt16
(
message
,
56
)
!=
message
.
Length
)
{
string
msg
=
"Invalid Type3 message length."
;
throw
new
ArgumentException
(
msg
,
"message"
);
}
string
msg
=
"Invalid Type3 message length."
;
throw
new
ArgumentException
(
msg
,
"message"
);
}
if
(
message
.
Length
>=
64
)
{
...
...
@@ -109,28 +96,25 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
{
Flags
=
(
Common
.
NtlmFlags
)
0x8201
;
}
int
dom_len
=
LittleEndian
.
ToUInt16
(
message
,
28
);
int
dom_off
=
LittleEndian
.
ToUInt16
(
message
,
32
);
this
.
Domain
=
DecodeString
(
message
,
dom_off
,
dom_len
);
int
domLen
=
LittleEndian
.
ToUInt16
(
message
,
28
);
int
domOff
=
LittleEndian
.
ToUInt16
(
message
,
32
);
int
user_len
=
LittleEndian
.
ToUInt16
(
message
,
36
);
int
user_off
=
LittleEndian
.
ToUInt16
(
message
,
40
);
Domain
=
DecodeString
(
message
,
domOff
,
domLen
);
this
.
Username
=
DecodeString
(
message
,
user_off
,
user_len
);
}
int
userLen
=
LittleEndian
.
ToUInt16
(
message
,
36
);
int
userOff
=
LittleEndian
.
ToUInt16
(
message
,
40
);
string
DecodeString
(
byte
[]
buffer
,
int
offset
,
int
len
)
{
Username
=
DecodeString
(
message
,
userOff
,
userLen
);
}
string
DecodeString
(
byte
[]
buffer
,
int
offset
,
int
len
)
{
if
((
Flags
&
Common
.
NtlmFlags
.
NegotiateUnicode
)
!=
0
)
{
return
Encoding
.
Unicode
.
GetString
(
buffer
,
offset
,
len
);
}
else
{
return
Encoding
.
ASCII
.
GetString
(
buffer
,
offset
,
len
);
}
return
Encoding
.
ASCII
.
GetString
(
buffer
,
offset
,
len
);
}
protected
bool
CheckHeader
(
byte
[]
message
)
...
...
@@ -140,8 +124,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
if
(
message
[
i
]
!=
header
[
i
])
return
false
;
}
return
(
LittleEndian
.
ToUInt32
(
message
,
8
)
==
_
type
);
return
(
LittleEndian
.
ToUInt32
(
message
,
8
)
==
type
);
}
}
}
Titanium.Web.Proxy/Network/WinAuth/Security/State.cs
View file @
70c107a4
namespace
Titanium.Web.Proxy.Network.WinAuth.Security
{
using
System
;
using
System
;
namespace
Titanium.Web.Proxy.Network.WinAuth.Security
{
/// <summary>
/// Status of authenticated session
/// </summary>
...
...
@@ -9,10 +9,10 @@
{
internal
State
()
{
this
.
Credentials
=
new
Common
.
SecurityHandle
(
0
);
this
.
Context
=
new
Common
.
SecurityHandle
(
0
);
Credentials
=
new
Common
.
SecurityHandle
(
0
);
Context
=
new
Common
.
SecurityHandle
(
0
);
this
.
LastSeen
=
DateTime
.
Now
;
LastSeen
=
DateTime
.
Now
;
}
/// <summary>
...
...
@@ -32,13 +32,13 @@
internal
void
ResetHandles
()
{
this
.
Credentials
.
Reset
();
this
.
Context
.
Reset
();
Credentials
.
Reset
();
Context
.
Reset
();
}
internal
void
UpdatePresence
()
{
this
.
LastSeen
=
DateTime
.
Now
;
LastSeen
=
DateTime
.
Now
;
}
}
}
Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs
View file @
70c107a4
// http://pinvoke.net/default.aspx/secur32/InitializeSecurityContext.html
using
System
;
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.Linq
;
using
System.Runtime.InteropServices
;
using
System.Security.Principal
;
using
System.Threading.Tasks
;
namespace
Titanium.Web.Proxy.Network.WinAuth.Security
{
using
System
;
using
System.Linq
;
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.Runtime.InteropServices
;
using
System.Security.Principal
;
using
static
Common
;
using
System.Threading.Tasks
;
internal
class
WinAuthEndPoint
{
/// <summary>
/// Keep track of auth states for reuse in final challenge response
/// </summary>
private
static
IDictionary
<
Guid
,
State
>
authStates
=
new
ConcurrentDictionary
<
Guid
,
State
>();
private
static
readonly
IDictionary
<
Guid
,
State
>
authStates
=
new
ConcurrentDictionary
<
Guid
,
State
>();
/// <summary>
...
...
@@ -27,17 +27,14 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
/// <param name="authScheme"></param>
/// <param name="requestId"></param>
/// <returns></returns>
internal
static
byte
[]
AcquireInitialSecurityToken
(
string
hostname
,
string
authScheme
,
Guid
requestId
)
internal
static
byte
[]
AcquireInitialSecurityToken
(
string
hostname
,
string
authScheme
,
Guid
requestId
)
{
byte
[]
token
=
null
;
byte
[]
token
;
//null for initial call
SecurityBufferDesciption
serverToken
=
new
SecurityBufferDesciption
();
var
serverToken
=
new
SecurityBufferDesciption
();
SecurityBufferDesciption
clientToken
=
new
SecurityBufferDesciption
(
MaximumTokenSize
);
var
clientToken
=
new
SecurityBufferDesciption
(
MaximumTokenSize
);
try
{
...
...
@@ -53,7 +50,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
IntPtr
.
Zero
,
0
,
IntPtr
.
Zero
,
ref
state
.
Credentials
,
ref
state
.
Credentials
,
ref
NewLifeTime
);
if
(
result
!=
SuccessfulResult
)
...
...
@@ -70,9 +67,9 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
SecurityNativeDataRepresentation
,
ref
serverToken
,
0
,
out
state
.
Context
,
out
state
.
Context
,
out
clientToken
,
out
NewContextAttributes
,
out
NewContextAttributes
,
out
NewLifeTime
);
...
...
@@ -101,17 +98,14 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
/// <param name="serverChallenge"></param>
/// <param name="requestId"></param>
/// <returns></returns>
internal
static
byte
[]
AcquireFinalSecurityToken
(
string
hostname
,
byte
[]
serverChallenge
,
Guid
requestId
)
internal
static
byte
[]
AcquireFinalSecurityToken
(
string
hostname
,
byte
[]
serverChallenge
,
Guid
requestId
)
{
byte
[]
token
=
null
;
byte
[]
token
;
//user server challenge
SecurityBufferDesciption
serverToken
=
new
SecurityBufferDesciption
(
serverChallenge
);
var
serverToken
=
new
SecurityBufferDesciption
(
serverChallenge
);
SecurityBufferDesciption
clientToken
=
new
SecurityBufferDesciption
(
MaximumTokenSize
);
var
clientToken
=
new
SecurityBufferDesciption
(
MaximumTokenSize
);
try
{
...
...
@@ -140,7 +134,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
// Client challenge issue operation failed.
return
null
;
}
authStates
.
Remove
(
requestId
);
token
=
clientToken
.
GetBytes
();
}
...
...
@@ -152,7 +146,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
return
token
;
}
/// <summary>
/// Clear any hanging states
/// </summary>
...
...
@@ -161,9 +155,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
{
var
cutOff
=
DateTime
.
Now
.
AddMinutes
(-
1
*
stateCacheTimeOutMinutes
);
var
outdated
=
authStates
.
Where
(
x
=>
x
.
Value
.
LastSeen
<
cutOff
)
.
ToList
();
var
outdated
=
authStates
.
Where
(
x
=>
x
.
Value
.
LastSeen
<
cutOff
).
ToList
();
foreach
(
var
cache
in
outdated
)
{
...
...
@@ -177,46 +169,45 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
#
region
Native
calls
to
secur32
.
dll
[
DllImport
(
"secur32.dll"
,
SetLastError
=
true
)]
static
extern
int
InitializeSecurityContext
(
ref
SecurityHandle
phCredential
,
//PCredHandle
IntPtr
phContext
,
//PCtxtHandle
string
pszTargetName
,
int
fContextReq
,
int
R
eserved1
,
int
T
argetDataRep
,
ref
SecurityBufferDesciption
pInput
,
//PSecBufferDesc SecBufferDesc
int
R
eserved2
,
out
SecurityHandle
phNewContext
,
//PCtxtHandle
out
SecurityBufferDesciption
pOutput
,
//PSecBufferDesc SecBufferDesc
out
uint
pfContextAttr
,
//managed ulong == 64 bits!!!
out
SecurityInteger
ptsExpiry
);
//PTimeStamp
static
extern
int
InitializeSecurityContext
(
ref
SecurityHandle
phCredential
,
//PCredHandle
IntPtr
phContext
,
//PCtxtHandle
string
pszTargetName
,
int
fContextReq
,
int
r
eserved1
,
int
t
argetDataRep
,
ref
SecurityBufferDesciption
pInput
,
//PSecBufferDesc SecBufferDesc
int
r
eserved2
,
out
SecurityHandle
phNewContext
,
//PCtxtHandle
out
SecurityBufferDesciption
pOutput
,
//PSecBufferDesc SecBufferDesc
out
uint
pfContextAttr
,
//managed ulong == 64 bits!!!
out
SecurityInteger
ptsExpiry
);
//PTimeStamp
[
DllImport
(
"secur32"
,
CharSet
=
CharSet
.
Auto
,
SetLastError
=
true
)]
static
extern
int
InitializeSecurityContext
(
ref
SecurityHandle
phCredential
,
//PCredHandle
ref
SecurityHandle
phContext
,
//PCtxtHandle
string
pszTargetName
,
int
fContextReq
,
int
R
eserved1
,
int
T
argetDataRep
,
ref
SecurityBufferDesciption
S
ecBufferDesc
,
//PSecBufferDesc SecBufferDesc
int
R
eserved2
,
out
SecurityHandle
phNewContext
,
//PCtxtHandle
out
SecurityBufferDesciption
pOutput
,
//PSecBufferDesc SecBufferDesc
out
uint
pfContextAttr
,
//managed ulong == 64 bits!!!
out
SecurityInteger
ptsExpiry
);
//PTimeStamp
static
extern
int
InitializeSecurityContext
(
ref
SecurityHandle
phCredential
,
//PCredHandle
ref
SecurityHandle
phContext
,
//PCtxtHandle
string
pszTargetName
,
int
fContextReq
,
int
r
eserved1
,
int
t
argetDataRep
,
ref
SecurityBufferDesciption
s
ecBufferDesc
,
//PSecBufferDesc SecBufferDesc
int
r
eserved2
,
out
SecurityHandle
phNewContext
,
//PCtxtHandle
out
SecurityBufferDesciption
pOutput
,
//PSecBufferDesc SecBufferDesc
out
uint
pfContextAttr
,
//managed ulong == 64 bits!!!
out
SecurityInteger
ptsExpiry
);
//PTimeStamp
[
DllImport
(
"secur32.dll"
,
CharSet
=
CharSet
.
Auto
,
SetLastError
=
false
)]
private
static
extern
int
AcquireCredentialsHandle
(
string
pszPrincipal
,
//SEC_CHAR*
string
pszPackage
,
//SEC_CHAR* //"Kerberos","NTLM","Negotiative"
string
pszPrincipal
,
//SEC_CHAR*
string
pszPackage
,
//SEC_CHAR* //"Kerberos","NTLM","Negotiative"
int
fCredentialUse
,
IntPtr
PAuthenticationID
,
//_LUID AuthenticationID,//pvLogonID, //PLUID
IntPtr
pAuthData
,
//PVOID
int
pGetKeyFn
,
//SEC_GET_KEY_FN
IntPtr
pvGetKeyArgument
,
//PVOID
ref
Common
.
SecurityHandle
phCredential
,
//SecHandle //PCtxtHandle ref
ref
Common
.
SecurityInteger
ptsExpiry
);
//PTimeStamp //TimeStamp ref
IntPtr
pAuthenticationId
,
//_LUID AuthenticationID,//pvLogonID, //PLUID
IntPtr
pAuthData
,
//PVOID
int
pGetKeyFn
,
//SEC_GET_KEY_FN
IntPtr
pvGetKeyArgument
,
//PVOID
ref
SecurityHandle
phCredential
,
//SecHandle //PCtxtHandle ref
ref
SecurityInteger
ptsExpiry
);
//PTimeStamp //TimeStamp ref
#
endregion
}
}
Titanium.Web.Proxy/Network/WinAuth/WinAuthHandler.cs
View file @
70c107a4
using
Titanium.Web.Proxy.Network.WinAuth.Security
;
using
System
;
using
System
;
using
Titanium.Web.Proxy.Network.WinAuth.Security
;
namespace
Titanium.Web.Proxy.Network.WinAuth
{
...
...
@@ -18,11 +18,10 @@ namespace Titanium.Web.Proxy.Network.WinAuth
/// <param name="authScheme"></param>
/// <param name="requestId"></param>
/// <returns></returns>
public
static
string
GetInitialAuthToken
(
string
serverHostname
,
string
authScheme
,
Guid
requestId
)
public
static
string
GetInitialAuthToken
(
string
serverHostname
,
string
authScheme
,
Guid
requestId
)
{
var
tokenBytes
=
WinAuthEndPoint
.
AcquireInitialSecurityToken
(
serverHostname
,
authScheme
,
requestId
);
return
string
.
Concat
(
" "
,
Convert
.
ToBase64String
(
tokenBytes
));
var
tokenBytes
=
WinAuthEndPoint
.
AcquireInitialSecurityToken
(
serverHostname
,
authScheme
,
requestId
);
return
string
.
Concat
(
" "
,
Convert
.
ToBase64String
(
tokenBytes
));
}
...
...
@@ -33,14 +32,11 @@ namespace Titanium.Web.Proxy.Network.WinAuth
/// <param name="serverToken"></param>
/// <param name="requestId"></param>
/// <returns></returns>
public
static
string
GetFinalAuthToken
(
string
serverHostname
,
string
serverToken
,
Guid
requestId
)
public
static
string
GetFinalAuthToken
(
string
serverHostname
,
string
serverToken
,
Guid
requestId
)
{
var
tokenBytes
=
WinAuthEndPoint
.
AcquireFinalSecurityToken
(
serverHostname
,
Convert
.
FromBase64String
(
serverToken
),
requestId
);
var
tokenBytes
=
WinAuthEndPoint
.
AcquireFinalSecurityToken
(
serverHostname
,
Convert
.
FromBase64String
(
serverToken
),
requestId
);
return
string
.
Concat
(
" "
,
Convert
.
ToBase64String
(
tokenBytes
));
}
}
}
Titanium.Web.Proxy/ProxyAuthorizationHandler.cs
View file @
70c107a4
...
...
@@ -30,8 +30,9 @@ namespace Titanium.Web.Proxy
}
var
header
=
httpHeaders
.
FirstOrDefault
(
t
=>
t
.
Name
==
"Proxy-Authorization"
);
if
(
header
==
null
)
throw
new
NullReferenceException
();
var
headerValue
=
header
.
Value
.
Trim
();
if
(
header
==
null
)
throw
new
NullReferenceException
();
string
headerValue
=
header
.
Value
.
Trim
();
if
(!
headerValue
.
StartsWith
(
"basic"
,
StringComparison
.
CurrentCultureIgnoreCase
))
{
//Return not authorized
...
...
@@ -41,7 +42,7 @@ namespace Titanium.Web.Proxy
headerValue
=
headerValue
.
Substring
(
5
).
Trim
();
var
decoded
=
Encoding
.
UTF8
.
GetString
(
Convert
.
FromBase64String
(
headerValue
));
string
decoded
=
Encoding
.
UTF8
.
GetString
(
Convert
.
FromBase64String
(
headerValue
));
if
(
decoded
.
Contains
(
":"
)
==
false
)
{
//Return not authorized
...
...
@@ -49,8 +50,8 @@ namespace Titanium.Web.Proxy
return
false
;
}
var
username
=
decoded
.
Substring
(
0
,
decoded
.
IndexOf
(
':'
));
var
password
=
decoded
.
Substring
(
decoded
.
IndexOf
(
':'
)
+
1
);
string
username
=
decoded
.
Substring
(
0
,
decoded
.
IndexOf
(
':'
));
string
password
=
decoded
.
Substring
(
decoded
.
IndexOf
(
':'
)
+
1
);
return
await
AuthenticateUserFunc
(
username
,
password
);
}
catch
(
Exception
e
)
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
70c107a4
...
...
@@ -67,9 +67,7 @@ namespace Titanium.Web.Proxy
/// <summary>
/// Set firefox to use default system proxy
/// </summary>
private
FireFoxProxySettingsManager
firefoxProxySettingsManager
=
new
FireFoxProxySettingsManager
();
private
readonly
FireFoxProxySettingsManager
firefoxProxySettingsManager
=
new
FireFoxProxySettingsManager
();
/// <summary>
/// Buffer size used throughout this proxy
...
...
@@ -255,15 +253,13 @@ namespace Titanium.Web.Proxy
/// <summary>
/// List of supported Ssl versions
/// </summary>
public
SslProtocols
SupportedSslProtocols
{
get
;
set
;
}
=
SslProtocols
.
Tls
|
SslProtocols
.
Tls11
|
SslProtocols
.
Tls12
|
SslProtocols
.
Ssl3
;
public
SslProtocols
SupportedSslProtocols
{
get
;
set
;
}
=
SslProtocols
.
Tls
|
SslProtocols
.
Tls11
|
SslProtocols
.
Tls12
|
SslProtocols
.
Ssl3
;
/// <summary>
/// Total number of active client connections
/// </summary>
public
int
ClientConnectionCount
=>
clientConnectionCount
;
/// <summary>
/// Total number of active server connections
/// </summary>
...
...
@@ -293,7 +289,7 @@ namespace Titanium.Web.Proxy
{
systemProxySettingsManager
=
new
SystemProxyManager
();
}
CertificateManager
=
new
CertificateManager
(
ExceptionFunc
);
if
(
rootCertificateName
!=
null
)
{
...
...
@@ -312,8 +308,7 @@ namespace Titanium.Web.Proxy
/// <param name="endPoint"></param>
public
void
AddEndPoint
(
ProxyEndPoint
endPoint
)
{
if
(
ProxyEndPoints
.
Any
(
x
=>
x
.
IpAddress
.
Equals
(
endPoint
.
IpAddress
)
&&
endPoint
.
Port
!=
0
&&
x
.
Port
==
endPoint
.
Port
))
if
(
ProxyEndPoints
.
Any
(
x
=>
x
.
IpAddress
.
Equals
(
endPoint
.
IpAddress
)
&&
endPoint
.
Port
!=
0
&&
x
.
Port
==
endPoint
.
Port
))
{
throw
new
Exception
(
"Cannot add another endpoint to same port & ip address"
);
}
...
...
@@ -412,7 +407,9 @@ namespace Titanium.Web.Proxy
systemProxySettingsManager
.
SetProxy
(
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Any
)
|
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Loopback
)
?
"127.0.0.1"
:
endPoint
.
IpAddress
.
ToString
(),
Equals
(
endPoint
.
IpAddress
,
IPAddress
.
Loopback
)
?
"127.0.0.1"
:
endPoint
.
IpAddress
.
ToString
(),
endPoint
.
Port
,
protocolType
);
...
...
@@ -524,7 +521,7 @@ namespace Titanium.Web.Proxy
}
}
if
(
ForwardToUpstreamGateway
if
(
ForwardToUpstreamGateway
&&
GetCustomUpStreamHttpProxyFunc
==
null
&&
GetCustomUpStreamHttpsProxyFunc
==
null
&&
systemProxySettingsManager
!=
null
)
{
...
...
@@ -565,7 +562,7 @@ namespace Titanium.Web.Proxy
if
(!
RunTime
.
IsRunningOnMono
)
{
var
setAsSystemProxy
=
ProxyEndPoints
.
OfType
<
ExplicitProxyEndPoint
>().
Any
(
x
=>
x
.
IsSystemHttpProxy
||
x
.
IsSystemHttpsProxy
);
bool
setAsSystemProxy
=
ProxyEndPoints
.
OfType
<
ExplicitProxyEndPoint
>().
Any
(
x
=>
x
.
IsSystemHttpProxy
||
x
.
IsSystemHttpsProxy
);
if
(
setAsSystemProxy
)
{
...
...
@@ -618,7 +615,8 @@ namespace Titanium.Web.Proxy
/// <param name="endPoint"></param>
private
void
ValidateEndPointAsSystemProxy
(
ExplicitProxyEndPoint
endPoint
)
{
if
(
endPoint
==
null
)
throw
new
ArgumentNullException
(
nameof
(
endPoint
));
if
(
endPoint
==
null
)
throw
new
ArgumentNullException
(
nameof
(
endPoint
));
if
(
ProxyEndPoints
.
Contains
(
endPoint
)
==
false
)
{
throw
new
Exception
(
"Cannot set endPoints not added to proxy as system proxy"
);
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
70c107a4
...
...
@@ -33,19 +33,22 @@ namespace Titanium.Web.Proxy
/// <returns></returns>
private
async
Task
HandleClient
(
ExplicitProxyEndPoint
endPoint
,
TcpClient
tcpClient
)
{
var
disposed
=
false
;
bool
disposed
=
false
;
var
clientStream
=
new
CustomBufferedStream
(
tcpClient
.
GetStream
(),
BufferSize
);
var
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
var
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
var
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
Uri
httpRemoteUri
;
try
{
//read the first line HTTP command
var
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
string
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
if
(
string
.
IsNullOrEmpty
(
httpCmd
))
{
...
...
@@ -56,7 +59,7 @@ namespace Titanium.Web.Proxy
var
httpCmdSplit
=
httpCmd
.
Split
(
ProxyConstants
.
SpaceSplit
,
3
);
//Find the request Verb
var
httpVerb
=
httpCmdSplit
[
0
].
ToUpper
();
string
httpVerb
=
httpCmdSplit
[
0
].
ToUpper
();
httpRemoteUri
=
httpVerb
==
"CONNECT"
?
new
Uri
(
"http://"
+
httpCmdSplit
[
1
])
:
new
Uri
(
httpCmdSplit
[
1
]);
...
...
@@ -64,7 +67,7 @@ namespace Titanium.Web.Proxy
var
version
=
HttpHeader
.
Version11
;
if
(
httpCmdSplit
.
Length
==
3
)
{
var
httpVersion
=
httpCmdSplit
[
2
].
Trim
();
string
httpVersion
=
httpCmdSplit
[
2
].
Trim
();
if
(
string
.
Equals
(
httpVersion
,
"HTTP/1.0"
,
StringComparison
.
OrdinalIgnoreCase
))
{
...
...
@@ -88,8 +91,7 @@ namespace Titanium.Web.Proxy
List
<
HttpHeader
>
connectRequestHeaders
=
null
;
//Client wants to create a secure tcp tunnel (its a HTTPS request)
if
(
httpVerb
==
"CONNECT"
&&
!
excluded
&&
endPoint
.
RemoteHttpsPorts
.
Contains
(
httpRemoteUri
.
Port
))
if
(
httpVerb
==
"CONNECT"
&&
!
excluded
&&
endPoint
.
RemoteHttpsPorts
.
Contains
(
httpRemoteUri
.
Port
))
{
httpRemoteUri
=
new
Uri
(
"https://"
+
httpCmdSplit
[
1
]);
connectRequestHeaders
=
new
List
<
HttpHeader
>();
...
...
@@ -115,21 +117,22 @@ namespace Titanium.Web.Proxy
{
sslStream
=
new
SslStream
(
clientStream
);
var
certName
=
HttpHelper
.
GetWildCardDomainName
(
httpRemoteUri
.
Host
);
string
certName
=
HttpHelper
.
GetWildCardDomainName
(
httpRemoteUri
.
Host
);
var
certificate
=
endPoint
.
GenericCertificate
??
CertificateManager
.
CreateCertificate
(
certName
,
false
);
var
certificate
=
endPoint
.
GenericCertificate
??
CertificateManager
.
CreateCertificate
(
certName
,
false
);
//Successfully managed to authenticate the client using the fake certificate
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SupportedSslProtocols
,
false
);
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SupportedSslProtocols
,
false
);
//HTTPS server created - we can now decrypt the client's traffic
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStreamReader
.
Dispose
();
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
}
catch
{
...
...
@@ -160,8 +163,7 @@ namespace Titanium.Web.Proxy
//Now create the request
disposed
=
await
HandleHttpSessionRequest
(
tcpClient
,
httpCmd
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
httpRemoteUri
.
Scheme
==
Uri
.
UriSchemeHttps
?
httpRemoteUri
.
Host
:
null
,
endPoint
,
connectRequestHeaders
);
httpRemoteUri
.
Scheme
==
Uri
.
UriSchemeHttps
?
httpRemoteUri
.
Host
:
null
,
endPoint
,
connectRequestHeaders
);
}
catch
(
Exception
e
)
{
...
...
@@ -202,17 +204,19 @@ namespace Titanium.Web.Proxy
var
certificate
=
CertificateManager
.
CreateCertificate
(
endPoint
.
GenericCertificateName
,
false
);
//Successfully managed to authenticate the client using the fake certificate
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SslProtocols
.
Tls
,
false
);
await
sslStream
.
AuthenticateAsServerAsync
(
certificate
,
false
,
SslProtocols
.
Tls
,
false
);
//HTTPS server created - we can now decrypt the client's traffic
}
clientStreamReader
=
new
CustomBinaryReader
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
clientStreamWriter
=
new
StreamWriter
(
clientStream
)
{
NewLine
=
ProxyConstants
.
NewLine
};
//now read the request line
var
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
string
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
//Now create the request
disposed
=
await
HandleHttpSessionRequest
(
tcpClient
,
httpCmd
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
...
...
@@ -283,13 +287,13 @@ namespace Titanium.Web.Proxy
//break up the line into three components (method, remote URL & Http Version)
var
httpCmdSplit
=
httpCmd
.
Split
(
ProxyConstants
.
SpaceSplit
,
3
);
var
httpMethod
=
httpCmdSplit
[
0
];
string
httpMethod
=
httpCmdSplit
[
0
];
//find the request HTTP version
var
httpVersion
=
HttpHeader
.
Version11
;
if
(
httpCmdSplit
.
Length
==
3
)
{
var
httpVersionString
=
httpCmdSplit
[
2
].
Trim
();
string
httpVersionString
=
httpCmdSplit
[
2
].
Trim
();
if
(
string
.
Equals
(
httpVersionString
,
"HTTP/1.0"
,
StringComparison
.
OrdinalIgnoreCase
))
{
...
...
@@ -313,9 +317,7 @@ namespace Titanium.Web.Proxy
args
.
ProxyClient
.
ClientStreamWriter
=
clientStreamWriter
;
//proxy authorization check
if
(
httpsConnectHostname
==
null
&&
await
CheckAuthorization
(
clientStreamWriter
,
args
.
WebSession
.
Request
.
RequestHeaders
.
Values
)
==
false
)
if
(
httpsConnectHostname
==
null
&&
await
CheckAuthorization
(
clientStreamWriter
,
args
.
WebSession
.
Request
.
RequestHeaders
.
Values
)
==
false
)
{
args
.
Dispose
();
break
;
...
...
@@ -327,9 +329,7 @@ namespace Titanium.Web.Proxy
//if win auth is enabled
//we need a cache of request body
//so that we can send it after authentication in WinAuthHandler.cs
if
(
EnableWinAuth
&&
!
RunTime
.
IsRunningOnMono
&&
args
.
WebSession
.
Request
.
HasBody
)
if
(
EnableWinAuth
&&
!
RunTime
.
IsRunningOnMono
&&
args
.
WebSession
.
Request
.
HasBody
)
{
await
args
.
GetRequestBody
();
}
...
...
@@ -349,10 +349,8 @@ namespace Titanium.Web.Proxy
//if upgrading to websocket then relay the requet without reading the contents
if
(
args
.
WebSession
.
Request
.
UpgradeToWebSocket
)
{
await
TcpHelper
.
SendRaw
(
this
,
httpRemoteUri
.
Host
,
httpRemoteUri
.
Port
,
httpCmd
,
httpVersion
,
args
.
WebSession
.
Request
.
RequestHeaders
,
args
.
IsHttps
,
clientStream
,
tcpConnectionFactory
,
connection
);
await
TcpHelper
.
SendRaw
(
this
,
httpRemoteUri
.
Host
,
httpRemoteUri
.
Port
,
httpCmd
,
httpVersion
,
args
.
WebSession
.
Request
.
RequestHeaders
,
args
.
IsHttps
,
clientStream
,
tcpConnectionFactory
,
connection
);
args
.
Dispose
();
break
;
...
...
@@ -363,8 +361,7 @@ namespace Titanium.Web.Proxy
connection
=
await
GetServerConnection
(
args
);
}
//create a new connection if hostname changes
else
if
(!
connection
.
HostName
.
Equals
(
args
.
WebSession
.
Request
.
RequestUri
.
Host
,
StringComparison
.
OrdinalIgnoreCase
))
else
if
(!
connection
.
HostName
.
Equals
(
args
.
WebSession
.
Request
.
RequestUri
.
Host
,
StringComparison
.
OrdinalIgnoreCase
))
{
connection
.
Dispose
();
Interlocked
.
Decrement
(
ref
serverConnectionCount
);
...
...
@@ -380,7 +377,7 @@ namespace Titanium.Web.Proxy
args
.
Dispose
();
break
;
}
//if connection is closing exit
if
(
args
.
WebSession
.
Response
.
ResponseKeepAlive
==
false
)
{
...
...
@@ -415,8 +412,7 @@ namespace Titanium.Web.Proxy
/// <param name="args"></param>
/// <param name="closeConnection"></param>
/// <returns></returns>
private
async
Task
<
bool
>
HandleHttpSessionRequestInternal
(
TcpConnection
connection
,
SessionEventArgs
args
,
bool
closeConnection
)
private
async
Task
<
bool
>
HandleHttpSessionRequestInternal
(
TcpConnection
connection
,
SessionEventArgs
args
,
bool
closeConnection
)
{
bool
disposed
=
false
;
bool
keepAlive
=
false
;
...
...
@@ -438,14 +434,12 @@ namespace Titanium.Web.Proxy
{
if
(
args
.
WebSession
.
Request
.
Is100Continue
)
{
await
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"100"
,
"Continue"
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"100"
,
"Continue"
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
args
.
ProxyClient
.
ClientStreamWriter
.
WriteLineAsync
();
}
else
if
(
args
.
WebSession
.
Request
.
ExpectationFailed
)
{
await
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"417"
,
"Expectation Failed"
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"417"
,
"Expectation Failed"
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
args
.
ProxyClient
.
ClientStreamWriter
.
WriteLineAsync
();
}
}
...
...
@@ -465,7 +459,8 @@ namespace Titanium.Web.Proxy
{
if
(
args
.
WebSession
.
Request
.
ContentEncoding
!=
null
)
{
args
.
WebSession
.
Request
.
RequestBody
=
await
GetCompressedResponseBody
(
args
.
WebSession
.
Request
.
ContentEncoding
,
args
.
WebSession
.
Request
.
RequestBody
);
args
.
WebSession
.
Request
.
RequestBody
=
await
GetCompressedResponseBody
(
args
.
WebSession
.
Request
.
ContentEncoding
,
args
.
WebSession
.
Request
.
RequestBody
);
}
//chunked send is not supported as of now
args
.
WebSession
.
Request
.
ContentLength
=
args
.
WebSession
.
Request
.
RequestBody
.
Length
;
...
...
@@ -520,7 +515,8 @@ namespace Titanium.Web.Proxy
if
(!
disposed
&&
!
keepAlive
)
{
//dispose
Dispose
(
args
.
ProxyClient
.
ClientStream
,
args
.
ProxyClient
.
ClientStreamReader
,
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
ServerConnection
);
Dispose
(
args
.
ProxyClient
.
ClientStream
,
args
.
ProxyClient
.
ClientStreamReader
,
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
ServerConnection
);
}
}
...
...
@@ -532,8 +528,7 @@ namespace Titanium.Web.Proxy
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private
async
Task
<
TcpConnection
>
GetServerConnection
(
SessionEventArgs
args
)
private
async
Task
<
TcpConnection
>
GetServerConnection
(
SessionEventArgs
args
)
{
ExternalProxy
customUpStreamHttpProxy
=
null
;
ExternalProxy
customUpStreamHttpsProxy
=
null
;
...
...
@@ -574,8 +569,7 @@ namespace Titanium.Web.Proxy
/// <returns></returns>
private
async
Task
WriteConnectResponse
(
StreamWriter
clientStreamWriter
,
Version
httpVersion
)
{
await
clientStreamWriter
.
WriteLineAsync
(
$"HTTP/
{
httpVersion
.
Major
}
.
{
httpVersion
.
Minor
}
200 Connection established"
);
await
clientStreamWriter
.
WriteLineAsync
(
$"HTTP/
{
httpVersion
.
Major
}
.
{
httpVersion
.
Minor
}
200 Connection established"
);
await
clientStreamWriter
.
WriteLineAsync
(
$"Timestamp:
{
DateTime
.
Now
}
"
);
await
clientStreamWriter
.
WriteLineAsync
();
await
clientStreamWriter
.
FlushAsync
();
...
...
Titanium.Web.Proxy/ResponseHandler.cs
View file @
70c107a4
...
...
@@ -32,13 +32,13 @@ namespace Titanium.Web.Proxy
await
args
.
WebSession
.
ReceiveResponse
();
//check for windows authentication
if
(
EnableWinAuth
if
(
EnableWinAuth
&&
!
RunTime
.
IsRunningOnMono
&&
args
.
WebSession
.
Response
.
ResponseStatusCode
==
"401"
)
{
var
disposed
=
await
Handle401UnAuthorized
(
args
);
if
(
disposed
)
bool
disposed
=
await
Handle401UnAuthorized
(
args
);
if
(
disposed
)
{
return
true
;
}
...
...
@@ -58,7 +58,7 @@ namespace Titanium.Web.Proxy
{
//clear current response
await
args
.
ClearResponse
();
var
disposed
=
await
HandleHttpSessionRequestInternal
(
args
.
WebSession
.
ServerConnection
,
args
,
false
);
bool
disposed
=
await
HandleHttpSessionRequestInternal
(
args
.
WebSession
.
ServerConnection
,
args
,
false
);
return
disposed
;
}
...
...
@@ -67,14 +67,12 @@ namespace Titanium.Web.Proxy
//Write back to client 100-conitinue response if that's what server returned
if
(
args
.
WebSession
.
Response
.
Is100Continue
)
{
await
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"100"
,
"Continue"
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"100"
,
"Continue"
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
args
.
ProxyClient
.
ClientStreamWriter
.
WriteLineAsync
();
}
else
if
(
args
.
WebSession
.
Response
.
ExpectationFailed
)
{
await
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"417"
,
"Expectation Failed"
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
WriteResponseStatus
(
args
.
WebSession
.
Response
.
HttpVersion
,
"417"
,
"Expectation Failed"
,
args
.
ProxyClient
.
ClientStreamWriter
);
await
args
.
ProxyClient
.
ClientStreamWriter
.
WriteLineAsync
();
}
...
...
@@ -84,8 +82,8 @@ namespace Titanium.Web.Proxy
if
(
args
.
WebSession
.
Response
.
ResponseBodyRead
)
{
var
isChunked
=
args
.
WebSession
.
Response
.
IsChunked
;
var
contentEncoding
=
args
.
WebSession
.
Response
.
ContentEncoding
;
bool
isChunked
=
args
.
WebSession
.
Response
.
IsChunked
;
string
contentEncoding
=
args
.
WebSession
.
Response
.
ContentEncoding
;
if
(
contentEncoding
!=
null
)
{
...
...
@@ -110,20 +108,17 @@ namespace Titanium.Web.Proxy
//Write body only if response is chunked or content length >0
//Is none are true then check if connection:close header exist, if so write response until server or client terminates the connection
if
(
args
.
WebSession
.
Response
.
IsChunked
||
args
.
WebSession
.
Response
.
ContentLength
>
0
||
!
args
.
WebSession
.
Response
.
ResponseKeepAlive
)
if
(
args
.
WebSession
.
Response
.
IsChunked
||
args
.
WebSession
.
Response
.
ContentLength
>
0
||
!
args
.
WebSession
.
Response
.
ResponseKeepAlive
)
{
await
args
.
WebSession
.
ServerConnection
.
StreamReader
.
WriteResponseBody
(
BufferSize
,
args
.
ProxyClient
.
ClientStream
,
args
.
WebSession
.
Response
.
IsChunked
,
args
.
WebSession
.
Response
.
ContentLength
);
await
args
.
WebSession
.
ServerConnection
.
StreamReader
.
WriteResponseBody
(
BufferSize
,
args
.
ProxyClient
.
ClientStream
,
args
.
WebSession
.
Response
.
IsChunked
,
args
.
WebSession
.
Response
.
ContentLength
);
}
//write response if connection:keep-alive header exist and when version is http/1.0
//Because in Http 1.0 server can return a response without content-length (expectation being client would read until end of stream)
else
if
(
args
.
WebSession
.
Response
.
ResponseKeepAlive
&&
args
.
WebSession
.
Response
.
HttpVersion
.
Minor
==
0
)
{
await
args
.
WebSession
.
ServerConnection
.
StreamReader
.
WriteResponseBody
(
BufferSize
,
args
.
ProxyClient
.
ClientStream
,
args
.
WebSession
.
Response
.
IsChunked
,
args
.
WebSession
.
Response
.
ContentLength
);
await
args
.
WebSession
.
ServerConnection
.
StreamReader
.
WriteResponseBody
(
BufferSize
,
args
.
ProxyClient
.
ClientStream
,
args
.
WebSession
.
Response
.
IsChunked
,
args
.
WebSession
.
Response
.
ContentLength
);
}
}
...
...
@@ -132,8 +127,8 @@ namespace Titanium.Web.Proxy
catch
(
Exception
e
)
{
ExceptionFunc
(
new
ProxyHttpException
(
"Error occured whilst handling session response"
,
e
,
args
));
Dispose
(
args
.
ProxyClient
.
ClientStream
,
args
.
ProxyClient
.
ClientStreamReader
,
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
ServerConnection
);
Dispose
(
args
.
ProxyClient
.
ClientStream
,
args
.
ProxyClient
.
ClientStreamReader
,
args
.
ProxyClient
.
ClientStreamWriter
,
args
.
WebSession
.
ServerConnection
);
return
true
;
}
...
...
@@ -162,8 +157,7 @@ namespace Titanium.Web.Proxy
/// <param name="description"></param>
/// <param name="responseWriter"></param>
/// <returns></returns>
private
async
Task
WriteResponseStatus
(
Version
version
,
string
code
,
string
description
,
StreamWriter
responseWriter
)
private
async
Task
WriteResponseStatus
(
Version
version
,
string
code
,
string
description
,
StreamWriter
responseWriter
)
{
await
responseWriter
.
WriteLineAsync
(
$"HTTP/
{
version
.
Major
}
.
{
version
.
Minor
}
{
code
}
{
description
}
"
);
}
...
...
@@ -204,8 +198,8 @@ namespace Titanium.Web.Proxy
private
void
FixProxyHeaders
(
Dictionary
<
string
,
HttpHeader
>
headers
)
{
//If proxy-connection close was returned inform to close the connection
var
hasProxyHeader
=
headers
.
ContainsKey
(
"proxy-connection"
);
var
hasConnectionheader
=
headers
.
ContainsKey
(
"connection"
);
bool
hasProxyHeader
=
headers
.
ContainsKey
(
"proxy-connection"
);
bool
hasConnectionheader
=
headers
.
ContainsKey
(
"connection"
);
if
(
hasProxyHeader
)
{
...
...
@@ -231,10 +225,7 @@ namespace Titanium.Web.Proxy
/// <param name="clientStreamReader"></param>
/// <param name="clientStreamWriter"></param>
/// <param name="serverConnection"></param>
private
void
Dispose
(
Stream
clientStream
,
CustomBinaryReader
clientStreamReader
,
StreamWriter
clientStreamWriter
,
TcpConnection
serverConnection
)
private
void
Dispose
(
Stream
clientStream
,
CustomBinaryReader
clientStreamReader
,
StreamWriter
clientStreamWriter
,
TcpConnection
serverConnection
)
{
clientStream
?.
Close
();
clientStream
?.
Dispose
();
...
...
Titanium.Web.Proxy/Shared/ProxyConstants.cs
View file @
70c107a4
...
...
@@ -16,8 +16,7 @@ namespace Titanium.Web.Proxy.Shared
internal
static
readonly
byte
[]
NewLineBytes
=
Encoding
.
ASCII
.
GetBytes
(
NewLine
);
internal
static
readonly
byte
[]
ChunkEnd
=
Encoding
.
ASCII
.
GetBytes
(
0.
ToString
(
"x2"
)
+
NewLine
+
NewLine
);
internal
static
readonly
byte
[]
ChunkEnd
=
Encoding
.
ASCII
.
GetBytes
(
0.
ToString
(
"x2"
)
+
NewLine
+
NewLine
);
internal
const
string
NewLine
=
"\r\n"
;
}
...
...
Titanium.Web.Proxy/WinAuthHandler.cs
View file @
70c107a4
...
...
@@ -5,30 +5,28 @@ using System.Threading.Tasks;
using
Titanium.Web.Proxy.EventArguments
;
using
Titanium.Web.Proxy.Models
;
using
Titanium.Web.Proxy.Network.WinAuth
;
using
Titanium.Web.Proxy.Extensions
;
using
Titanium.Web.Proxy.Helpers
;
namespace
Titanium.Web.Proxy
{
public
partial
class
ProxyServer
{
//possible header names
private
static
List
<
string
>
authHeaderNames
=
new
List
<
string
>()
{
"WWW-Authenticate"
,
//IIS 6.0 messed up names below
"WWWAuthenticate"
,
"NTLMAuthorization"
,
"NegotiateAuthorization"
,
"KerberosAuthorization"
};
private
static
List
<
string
>
authSchemes
=
new
List
<
string
>()
{
"NTLM"
,
"Negotiate"
,
"Kerberos"
};
private
static
readonly
List
<
string
>
authHeaderNames
=
new
List
<
string
>
{
"WWW-Authenticate"
,
//IIS 6.0 messed up names below
"WWWAuthenticate"
,
"NTLMAuthorization"
,
"NegotiateAuthorization"
,
"KerberosAuthorization"
};
private
static
readonly
List
<
string
>
authSchemes
=
new
List
<
string
>
{
"NTLM"
,
"Negotiate"
,
"Kerberos"
};
/// <summary>
/// Handle windows NTLM authentication
...
...
@@ -45,32 +43,27 @@ namespace Titanium.Web.Proxy
HttpHeader
authHeader
=
null
;
//check in non-unique headers first
var
header
=
args
.
WebSession
.
Response
.
NonUniqueResponseHeaders
.
FirstOrDefault
(
x
=>
authHeaderNames
.
Any
(
y
=>
x
.
Key
.
Equals
(
y
,
StringComparison
.
OrdinalIgnoreCase
)));
var
header
=
args
.
WebSession
.
Response
.
NonUniqueResponseHeaders
.
FirstOrDefault
(
x
=>
authHeaderNames
.
Any
(
y
=>
x
.
Key
.
Equals
(
y
,
StringComparison
.
OrdinalIgnoreCase
)));
if
(!
header
.
Equals
(
new
KeyValuePair
<
string
,
List
<
HttpHeader
>>()))
{
headerName
=
header
.
Key
;
}
if
(
headerName
!=
null
)
{
authHeader
=
args
.
WebSession
.
Response
.
NonUniqueResponseHeaders
[
headerName
]
.
Where
(
x
=>
authSchemes
.
Any
(
y
=>
x
.
Value
.
StartsWith
(
y
,
StringComparison
.
OrdinalIgnoreCase
)))
.
FirstOrDefault
();
authHeader
=
args
.
WebSession
.
Response
.
NonUniqueResponseHeaders
[
headerName
]
.
FirstOrDefault
(
x
=>
authSchemes
.
Any
(
y
=>
x
.
Value
.
StartsWith
(
y
,
StringComparison
.
OrdinalIgnoreCase
)));
}
//check in unique headers
if
(
authHeader
==
null
)
{
//check in non-unique headers first
var
uHeader
=
args
.
WebSession
.
Response
.
ResponseHeaders
.
FirstOrDefault
(
x
=>
authHeaderNames
.
Any
(
y
=>
x
.
Key
.
Equals
(
y
,
StringComparison
.
OrdinalIgnoreCase
)));
var
uHeader
=
args
.
WebSession
.
Response
.
ResponseHeaders
.
FirstOrDefault
(
x
=>
authHeaderNames
.
Any
(
y
=>
x
.
Key
.
Equals
(
y
,
StringComparison
.
OrdinalIgnoreCase
)));
if
(!
uHeader
.
Equals
(
new
KeyValuePair
<
string
,
HttpHeader
>()))
{
...
...
@@ -79,15 +72,16 @@ namespace Titanium.Web.Proxy
if
(
headerName
!=
null
)
{
authHeader
=
authSchemes
.
Any
(
x
=>
args
.
WebSession
.
Response
.
ResponseHeaders
[
headerName
].
Value
.
StartsWith
(
x
,
StringComparison
.
OrdinalIgnoreCase
))
?
args
.
WebSession
.
Response
.
ResponseHeaders
[
headerName
]
:
null
;
authHeader
=
authSchemes
.
Any
(
x
=>
args
.
WebSession
.
Response
.
ResponseHeaders
[
headerName
].
Value
.
StartsWith
(
x
,
StringComparison
.
OrdinalIgnoreCase
))
?
args
.
WebSession
.
Response
.
ResponseHeaders
[
headerName
]
:
null
;
}
}
if
(
authHeader
!=
null
)
{
var
scheme
=
authSchemes
.
FirstOrDefault
(
x
=>
authHeader
.
Value
.
Equals
(
x
,
StringComparison
.
OrdinalIgnoreCase
));
string
scheme
=
authSchemes
.
FirstOrDefault
(
x
=>
authHeader
.
Value
.
Equals
(
x
,
StringComparison
.
OrdinalIgnoreCase
));
//clear any existing headers to avoid confusing bad servers
if
(
args
.
WebSession
.
Request
.
NonUniqueRequestHeaders
.
ContainsKey
(
"Authorization"
))
...
...
@@ -98,10 +92,10 @@ namespace Titanium.Web.Proxy
//initial value will match exactly any of the schemes
if
(
scheme
!=
null
)
{
var
clientToken
=
WinAuthHandler
.
GetInitialAuthToken
(
args
.
WebSession
.
Request
.
Host
,
scheme
,
args
.
Id
);
string
clientToken
=
WinAuthHandler
.
GetInitialAuthToken
(
args
.
WebSession
.
Request
.
Host
,
scheme
,
args
.
Id
);
var
auth
=
new
HttpHeader
(
"Authorization"
,
string
.
Concat
(
scheme
,
clientToken
));
//replace existing authorization header if any
if
(
args
.
WebSession
.
Request
.
RequestHeaders
.
ContainsKey
(
"Authorization"
))
{
...
...
@@ -113,32 +107,28 @@ namespace Titanium.Web.Proxy
}
//don't need to send body for Authorization request
if
(
args
.
WebSession
.
Request
.
HasBody
)
if
(
args
.
WebSession
.
Request
.
HasBody
)
{
args
.
WebSession
.
Request
.
ContentLength
=
0
;
}
}
//challenge value will start with any of the scheme selected
else
{
scheme
=
authSchemes
.
FirstOrDefault
(
x
=>
authHeader
.
Value
.
StartsWith
(
x
,
StringComparison
.
OrdinalIgnoreCase
)
&&
authHeader
.
Value
.
Length
>
x
.
Length
+
1
);
scheme
=
authSchemes
.
FirstOrDefault
(
x
=>
authHeader
.
Value
.
StartsWith
(
x
,
StringComparison
.
OrdinalIgnoreCase
)
&&
authHeader
.
Value
.
Length
>
x
.
Length
+
1
);
var
serverToken
=
authHeader
.
Value
.
Substring
(
scheme
.
Length
+
1
);
var
clientToken
=
WinAuthHandler
.
GetFinalAuthToken
(
args
.
WebSession
.
Request
.
Host
,
serverToken
,
args
.
Id
);
string
serverToken
=
authHeader
.
Value
.
Substring
(
scheme
.
Length
+
1
);
string
clientToken
=
WinAuthHandler
.
GetFinalAuthToken
(
args
.
WebSession
.
Request
.
Host
,
serverToken
,
args
.
Id
);
//there will be an existing header from initial client request
args
.
WebSession
.
Request
.
RequestHeaders
[
"Authorization"
]
=
new
HttpHeader
(
"Authorization"
,
string
.
Concat
(
scheme
,
clientToken
));
args
.
WebSession
.
Request
.
RequestHeaders
[
"Authorization"
]
=
new
HttpHeader
(
"Authorization"
,
string
.
Concat
(
scheme
,
clientToken
));
//send body for final auth request
if
(
args
.
WebSession
.
Request
.
HasBody
)
{
args
.
WebSession
.
Request
.
ContentLength
=
args
.
WebSession
.
Request
.
RequestBody
.
Length
;
args
.
WebSession
.
Request
.
ContentLength
=
args
.
WebSession
.
Request
.
RequestBody
.
Length
;
}
}
//Need to revisit this.
...
...
@@ -150,13 +140,11 @@ namespace Titanium.Web.Proxy
//request again with updated authorization header
//and server cookies
var
disposed
=
await
HandleHttpSessionRequestInternal
(
args
.
WebSession
.
ServerConnection
,
args
,
false
);
bool
disposed
=
await
HandleHttpSessionRequestInternal
(
args
.
WebSession
.
ServerConnection
,
args
,
false
);
return
disposed
;
}
return
false
;
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment