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
a8497ab2
Commit
a8497ab2
authored
May 01, 2018
by
Honfika
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
space between // and text in comments (except when it is a commented code)
parent
bbd6f9b5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
291 additions
and
267 deletions
+291
-267
Program.cs
Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs
+2
-2
ProxyTestController.cs
.../Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
+65
-46
SslTests.cs
Tests/Titanium.Web.Proxy.IntegrationTests/SslTests.cs
+8
-8
CertificateManagerTests.cs
...s/Titanium.Web.Proxy.UnitTests/CertificateManagerTests.cs
+3
-3
CertificateHandler.cs
Titanium.Web.Proxy/CertificateHandler.cs
+6
-6
ExplicitClientHandler.cs
Titanium.Web.Proxy/ExplicitClientHandler.cs
+13
-13
HttpHelper.cs
Titanium.Web.Proxy/Helpers/HttpHelper.cs
+11
-11
HttpWriter.cs
Titanium.Web.Proxy/Helpers/HttpWriter.cs
+4
-4
SystemProxy.cs
Titanium.Web.Proxy/Helpers/SystemProxy.cs
+1
-1
Tcp.cs
Titanium.Web.Proxy/Helpers/Tcp.cs
+3
-3
HeaderCollection.cs
Titanium.Web.Proxy/Http/HeaderCollection.cs
+1
-1
HttpWebClient.cs
Titanium.Web.Proxy/Http/HttpWebClient.cs
+11
-11
Request.cs
Titanium.Web.Proxy/Http/Request.cs
+7
-7
RequestResponseBase.cs
Titanium.Web.Proxy/Http/RequestResponseBase.cs
+1
-1
Response.cs
Titanium.Web.Proxy/Http/Response.cs
+5
-5
GenericResponse.cs
Titanium.Web.Proxy/Http/Responses/GenericResponse.cs
+2
-2
BCCertificateMaker.cs
Titanium.Web.Proxy/Network/Certificate/BCCertificateMaker.cs
+1
-1
WinCertificateMaker.cs
...nium.Web.Proxy/Network/Certificate/WinCertificateMaker.cs
+11
-7
CertificateManager.cs
Titanium.Web.Proxy/Network/CertificateManager.cs
+24
-24
TcpConnectionFactory.cs
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
+3
-3
Common.cs
Titanium.Web.Proxy/Network/WinAuth/Security/Common.cs
+17
-17
Message.cs
Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs
+4
-4
WinAuthEndPoint.cs
...ium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs
+25
-25
ProxyAuthorizationHandler.cs
Titanium.Web.Proxy/ProxyAuthorizationHandler.cs
+4
-4
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+7
-7
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+22
-22
ResponseHandler.cs
Titanium.Web.Proxy/ResponseHandler.cs
+10
-10
TransparentClientHandler.cs
Titanium.Web.Proxy/TransparentClientHandler.cs
+5
-5
WinAuthHandler.cs
Titanium.Web.Proxy/WinAuthHandler.cs
+15
-14
No files found.
Examples/Titanium.Web.Proxy.Examples.Basic/Program.cs
View file @
a8497ab2
...
@@ -9,10 +9,10 @@ namespace Titanium.Web.Proxy.Examples.Basic
...
@@ -9,10 +9,10 @@ namespace Titanium.Web.Proxy.Examples.Basic
public
static
void
Main
(
string
[]
args
)
public
static
void
Main
(
string
[]
args
)
{
{
//fix console hang due to QuickEdit mode
//
fix console hang due to QuickEdit mode
ConsoleHelper
.
DisableQuickEditMode
();
ConsoleHelper
.
DisableQuickEditMode
();
//Start proxy controller
//
Start proxy controller
controller
.
StartProxy
();
controller
.
StartProxy
();
Console
.
WriteLine
(
"Hit any key to exit.."
);
Console
.
WriteLine
(
"Hit any key to exit.."
);
...
...
Examples/Titanium.Web.Proxy.Examples.Basic/ProxyTestController.cs
View file @
a8497ab2
This diff is collapsed.
Click to expand it.
Tests/Titanium.Web.Proxy.IntegrationTests/SslTests.cs
View file @
a8497ab2
...
@@ -17,8 +17,8 @@ namespace Titanium.Web.Proxy.IntegrationTests
...
@@ -17,8 +17,8 @@ namespace Titanium.Web.Proxy.IntegrationTests
//disable this test until CI is prepared to handle
//disable this test until CI is prepared to handle
public
void
TestSsl
()
public
void
TestSsl
()
{
{
//expand this to stress test to find
//
expand this to stress test to find
//why in long run proxy becomes unresponsive as per issue #184
//
why in long run proxy becomes unresponsive as per issue #184
string
testUrl
=
"https://google.com"
;
string
testUrl
=
"https://google.com"
;
int
proxyPort
=
8086
;
int
proxyPort
=
8086
;
var
proxy
=
new
ProxyTestController
();
var
proxy
=
new
ProxyTestController
();
...
@@ -62,8 +62,8 @@ namespace Titanium.Web.Proxy.IntegrationTests
...
@@ -62,8 +62,8 @@ namespace Titanium.Web.Proxy.IntegrationTests
var
explicitEndPoint
=
new
ExplicitProxyEndPoint
(
IPAddress
.
Any
,
proxyPort
,
true
);
var
explicitEndPoint
=
new
ExplicitProxyEndPoint
(
IPAddress
.
Any
,
proxyPort
,
true
);
//An explicit endpoint is where the client knows about the existance of a proxy
//
An explicit endpoint is where the client knows about the existance of a proxy
//So client sends request in a proxy friendly manner
//
So client sends request in a proxy friendly manner
proxyServer
.
AddEndPoint
(
explicitEndPoint
);
proxyServer
.
AddEndPoint
(
explicitEndPoint
);
proxyServer
.
Start
();
proxyServer
.
Start
();
...
@@ -84,14 +84,14 @@ namespace Titanium.Web.Proxy.IntegrationTests
...
@@ -84,14 +84,14 @@ namespace Titanium.Web.Proxy.IntegrationTests
proxyServer
.
Stop
();
proxyServer
.
Stop
();
}
}
//intecept & cancel, redirect or update requests
//
intecept & cancel, redirect or update requests
public
async
Task
OnRequest
(
object
sender
,
SessionEventArgs
e
)
public
async
Task
OnRequest
(
object
sender
,
SessionEventArgs
e
)
{
{
Debug
.
WriteLine
(
e
.
WebSession
.
Request
.
Url
);
Debug
.
WriteLine
(
e
.
WebSession
.
Request
.
Url
);
await
Task
.
FromResult
(
0
);
await
Task
.
FromResult
(
0
);
}
}
//Modify response
//
Modify response
public
async
Task
OnResponse
(
object
sender
,
SessionEventArgs
e
)
public
async
Task
OnResponse
(
object
sender
,
SessionEventArgs
e
)
{
{
await
Task
.
FromResult
(
0
);
await
Task
.
FromResult
(
0
);
...
@@ -104,7 +104,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
...
@@ -104,7 +104,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
/// <param name="e"></param>
/// <param name="e"></param>
public
Task
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
public
Task
OnCertificateValidation
(
object
sender
,
CertificateValidationEventArgs
e
)
{
{
//set IsValid to true/false based on Certificate Errors
//
set IsValid to true/false based on Certificate Errors
if
(
e
.
SslPolicyErrors
==
SslPolicyErrors
.
None
)
if
(
e
.
SslPolicyErrors
==
SslPolicyErrors
.
None
)
{
{
e
.
IsValid
=
true
;
e
.
IsValid
=
true
;
...
@@ -120,7 +120,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
...
@@ -120,7 +120,7 @@ namespace Titanium.Web.Proxy.IntegrationTests
/// <param name="e"></param>
/// <param name="e"></param>
public
Task
OnCertificateSelection
(
object
sender
,
CertificateSelectionEventArgs
e
)
public
Task
OnCertificateSelection
(
object
sender
,
CertificateSelectionEventArgs
e
)
{
{
//set e.clientCertificate to override
//
set e.clientCertificate to override
return
Task
.
FromResult
(
0
);
return
Task
.
FromResult
(
0
);
}
}
...
...
Tests/Titanium.Web.Proxy.UnitTests/CertificateManagerTests.cs
View file @
a8497ab2
...
@@ -33,7 +33,7 @@ namespace Titanium.Web.Proxy.UnitTests
...
@@ -33,7 +33,7 @@ namespace Titanium.Web.Proxy.UnitTests
{
{
tasks
.
AddRange
(
hostNames
.
Select
(
host
=>
Task
.
Run
(()
=>
tasks
.
AddRange
(
hostNames
.
Select
(
host
=>
Task
.
Run
(()
=>
{
{
//get the connection
//
get the connection
var
certificate
=
mgr
.
CreateCertificate
(
host
,
false
);
var
certificate
=
mgr
.
CreateCertificate
(
host
,
false
);
Assert
.
IsNotNull
(
certificate
);
Assert
.
IsNotNull
(
certificate
);
})));
})));
...
@@ -44,7 +44,7 @@ namespace Titanium.Web.Proxy.UnitTests
...
@@ -44,7 +44,7 @@ namespace Titanium.Web.Proxy.UnitTests
mgr
.
StopClearIdleCertificates
();
mgr
.
StopClearIdleCertificates
();
}
}
//uncomment this to compare WinCert maker performance with BC (BC takes more time for same test above)
//
uncomment this to compare WinCert maker performance with BC (BC takes more time for same test above)
[
TestMethod
]
[
TestMethod
]
public
async
Task
Simple_Create_Win_Certificate_Test
()
public
async
Task
Simple_Create_Win_Certificate_Test
()
{
{
...
@@ -66,7 +66,7 @@ namespace Titanium.Web.Proxy.UnitTests
...
@@ -66,7 +66,7 @@ namespace Titanium.Web.Proxy.UnitTests
{
{
tasks
.
AddRange
(
hostNames
.
Select
(
host
=>
Task
.
Run
(()
=>
tasks
.
AddRange
(
hostNames
.
Select
(
host
=>
Task
.
Run
(()
=>
{
{
//get the connection
//
get the connection
var
certificate
=
mgr
.
CreateCertificate
(
host
,
false
);
var
certificate
=
mgr
.
CreateCertificate
(
host
,
false
);
Assert
.
IsNotNull
(
certificate
);
Assert
.
IsNotNull
(
certificate
);
})));
})));
...
...
Titanium.Web.Proxy/CertificateHandler.cs
View file @
a8497ab2
...
@@ -19,7 +19,7 @@ namespace Titanium.Web.Proxy
...
@@ -19,7 +19,7 @@ namespace Titanium.Web.Proxy
internal
bool
ValidateServerCertificate
(
object
sender
,
X509Certificate
certificate
,
X509Chain
chain
,
internal
bool
ValidateServerCertificate
(
object
sender
,
X509Certificate
certificate
,
X509Chain
chain
,
SslPolicyErrors
sslPolicyErrors
)
SslPolicyErrors
sslPolicyErrors
)
{
{
//if user callback is registered then do it
//
if user callback is registered then do it
if
(
ServerCertificateValidationCallback
!=
null
)
if
(
ServerCertificateValidationCallback
!=
null
)
{
{
var
args
=
new
CertificateValidationEventArgs
var
args
=
new
CertificateValidationEventArgs
...
@@ -29,7 +29,7 @@ namespace Titanium.Web.Proxy
...
@@ -29,7 +29,7 @@ namespace Titanium.Web.Proxy
SslPolicyErrors
=
sslPolicyErrors
SslPolicyErrors
=
sslPolicyErrors
};
};
//why is the sender null?
//
why is the sender null?
ServerCertificateValidationCallback
.
InvokeAsync
(
this
,
args
,
exceptionFunc
).
Wait
();
ServerCertificateValidationCallback
.
InvokeAsync
(
this
,
args
,
exceptionFunc
).
Wait
();
return
args
.
IsValid
;
return
args
.
IsValid
;
}
}
...
@@ -39,8 +39,8 @@ namespace Titanium.Web.Proxy
...
@@ -39,8 +39,8 @@ namespace Titanium.Web.Proxy
return
true
;
return
true
;
}
}
//By default
//
By default
//do not allow this client to communicate with unauthenticated servers.
//
do not allow this client to communicate with unauthenticated servers.
return
false
;
return
false
;
}
}
...
@@ -77,7 +77,7 @@ namespace Titanium.Web.Proxy
...
@@ -77,7 +77,7 @@ namespace Titanium.Web.Proxy
clientCertificate
=
localCertificates
[
0
];
clientCertificate
=
localCertificates
[
0
];
}
}
//If user call back is registered
//
If user call back is registered
if
(
ClientCertificateSelectionCallback
!=
null
)
if
(
ClientCertificateSelectionCallback
!=
null
)
{
{
var
args
=
new
CertificateSelectionEventArgs
var
args
=
new
CertificateSelectionEventArgs
...
@@ -89,7 +89,7 @@ namespace Titanium.Web.Proxy
...
@@ -89,7 +89,7 @@ namespace Titanium.Web.Proxy
ClientCertificate
=
clientCertificate
ClientCertificate
=
clientCertificate
};
};
//why is the sender null?
//
why is the sender null?
ClientCertificateSelectionCallback
.
InvokeAsync
(
this
,
args
,
exceptionFunc
).
Wait
();
ClientCertificateSelectionCallback
.
InvokeAsync
(
this
,
args
,
exceptionFunc
).
Wait
();
return
args
.
ClientCertificate
;
return
args
.
ClientCertificate
;
}
}
...
...
Titanium.Web.Proxy/ExplicitClientHandler.cs
View file @
a8497ab2
...
@@ -43,10 +43,10 @@ namespace Titanium.Web.Proxy
...
@@ -43,10 +43,10 @@ namespace Titanium.Web.Proxy
string
connectHostname
=
null
;
string
connectHostname
=
null
;
TunnelConnectSessionEventArgs
connectArgs
=
null
;
TunnelConnectSessionEventArgs
connectArgs
=
null
;
//Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
//
Client wants to create a secure tcp tunnel (probably its a HTTPS or Websocket request)
if
(
await
HttpHelper
.
IsConnectMethod
(
clientStream
)
==
1
)
if
(
await
HttpHelper
.
IsConnectMethod
(
clientStream
)
==
1
)
{
{
//read the first line HTTP command
//
read the first line HTTP command
string
httpCmd
=
await
clientStream
.
ReadLineAsync
(
cancellationToken
);
string
httpCmd
=
await
clientStream
.
ReadLineAsync
(
cancellationToken
);
if
(
string
.
IsNullOrEmpty
(
httpCmd
))
if
(
string
.
IsNullOrEmpty
(
httpCmd
))
{
{
...
@@ -74,7 +74,7 @@ namespace Titanium.Web.Proxy
...
@@ -74,7 +74,7 @@ namespace Titanium.Web.Proxy
await
endPoint
.
InvokeBeforeTunnelConnectRequest
(
this
,
connectArgs
,
ExceptionFunc
);
await
endPoint
.
InvokeBeforeTunnelConnectRequest
(
this
,
connectArgs
,
ExceptionFunc
);
//filter out excluded host names
//
filter out excluded host names
bool
decryptSsl
=
endPoint
.
DecryptSsl
&&
connectArgs
.
DecryptSsl
;
bool
decryptSsl
=
endPoint
.
DecryptSsl
&&
connectArgs
.
DecryptSsl
;
if
(
connectArgs
.
DenyConnect
)
if
(
connectArgs
.
DenyConnect
)
...
@@ -89,7 +89,7 @@ namespace Titanium.Web.Proxy
...
@@ -89,7 +89,7 @@ namespace Titanium.Web.Proxy
};
};
}
}
//send the response
//
send the response
await
clientStreamWriter
.
WriteResponseAsync
(
connectArgs
.
WebSession
.
Response
,
await
clientStreamWriter
.
WriteResponseAsync
(
connectArgs
.
WebSession
.
Response
,
cancellationToken
:
cancellationToken
);
cancellationToken
:
cancellationToken
);
return
;
return
;
...
@@ -99,13 +99,13 @@ namespace Titanium.Web.Proxy
...
@@ -99,13 +99,13 @@ namespace Titanium.Web.Proxy
{
{
await
endPoint
.
InvokeBeforeTunnectConnectResponse
(
this
,
connectArgs
,
ExceptionFunc
);
await
endPoint
.
InvokeBeforeTunnectConnectResponse
(
this
,
connectArgs
,
ExceptionFunc
);
//send the response
//
send the response
await
clientStreamWriter
.
WriteResponseAsync
(
connectArgs
.
WebSession
.
Response
,
await
clientStreamWriter
.
WriteResponseAsync
(
connectArgs
.
WebSession
.
Response
,
cancellationToken
:
cancellationToken
);
cancellationToken
:
cancellationToken
);
return
;
return
;
}
}
//write back successfull CONNECT response
//
write back successfull CONNECT response
var
response
=
ConnectResponse
.
CreateSuccessfullConnectResponse
(
version
);
var
response
=
ConnectResponse
.
CreateSuccessfullConnectResponse
(
version
);
// Set ContentLength explicitly to properly handle HTTP 1.0
// Set ContentLength explicitly to properly handle HTTP 1.0
...
@@ -153,7 +153,7 @@ namespace Titanium.Web.Proxy
...
@@ -153,7 +153,7 @@ namespace Titanium.Web.Proxy
var
certificate
=
endPoint
.
GenericCertificate
??
var
certificate
=
endPoint
.
GenericCertificate
??
await
CertificateManager
.
CreateCertificateAsync
(
certName
);
await
CertificateManager
.
CreateCertificateAsync
(
certName
);
//Successfully managed to authenticate the client using the fake certificate
//
Successfully managed to authenticate the client using the fake certificate
var
options
=
new
SslServerAuthenticationOptions
();
var
options
=
new
SslServerAuthenticationOptions
();
if
(
http2Supproted
)
if
(
http2Supproted
)
{
{
...
@@ -170,7 +170,7 @@ namespace Titanium.Web.Proxy
...
@@ -170,7 +170,7 @@ namespace Titanium.Web.Proxy
options
.
CertificateRevocationCheckMode
=
X509RevocationMode
.
NoCheck
;
options
.
CertificateRevocationCheckMode
=
X509RevocationMode
.
NoCheck
;
await
sslStream
.
AuthenticateAsServerAsync
(
options
,
cancellationToken
);
await
sslStream
.
AuthenticateAsServerAsync
(
options
,
cancellationToken
);
//HTTPS server created - we can now decrypt the client's traffic
//
HTTPS server created - we can now decrypt the client's traffic
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
...
@@ -193,10 +193,10 @@ namespace Titanium.Web.Proxy
...
@@ -193,10 +193,10 @@ namespace Titanium.Web.Proxy
throw
new
Exception
(
"Session was terminated by user."
);
throw
new
Exception
(
"Session was terminated by user."
);
}
}
//Hostname is excluded or it is not an HTTPS connect
//
Hostname is excluded or it is not an HTTPS connect
if
(!
decryptSsl
||
!
isClientHello
)
if
(!
decryptSsl
||
!
isClientHello
)
{
{
//create new connection
//
create new connection
using
(
var
connection
=
await
GetServerConnection
(
connectArgs
,
true
,
cancellationToken
))
using
(
var
connection
=
await
GetServerConnection
(
connectArgs
,
true
,
cancellationToken
))
{
{
if
(
isClientHello
)
if
(
isClientHello
)
...
@@ -204,7 +204,7 @@ namespace Titanium.Web.Proxy
...
@@ -204,7 +204,7 @@ namespace Titanium.Web.Proxy
int
available
=
clientStream
.
Available
;
int
available
=
clientStream
.
Available
;
if
(
available
>
0
)
if
(
available
>
0
)
{
{
//send the buffered data
//
send the buffered data
var
data
=
BufferPool
.
GetBuffer
(
BufferSize
);
var
data
=
BufferPool
.
GetBuffer
(
BufferSize
);
try
try
...
@@ -260,7 +260,7 @@ namespace Titanium.Web.Proxy
...
@@ -260,7 +260,7 @@ namespace Titanium.Web.Proxy
throw
new
Exception
(
$"HTTP/2 Protocol violation. Empty string expected, '
{
line
}
' received"
);
throw
new
Exception
(
$"HTTP/2 Protocol violation. Empty string expected, '
{
line
}
' received"
);
}
}
//create new connection
//
create new connection
using
(
var
connection
=
await
GetServerConnection
(
connectArgs
,
true
,
cancellationToken
))
using
(
var
connection
=
await
GetServerConnection
(
connectArgs
,
true
,
cancellationToken
))
{
{
await
connection
.
StreamWriter
.
WriteLineAsync
(
"PRI * HTTP/2.0"
,
cancellationToken
);
await
connection
.
StreamWriter
.
WriteLineAsync
(
"PRI * HTTP/2.0"
,
cancellationToken
);
...
@@ -276,7 +276,7 @@ namespace Titanium.Web.Proxy
...
@@ -276,7 +276,7 @@ namespace Titanium.Web.Proxy
}
}
}
}
//Now create the request
//
Now create the request
await
HandleHttpSessionRequest
(
endPoint
,
clientConnection
,
clientStream
,
clientStreamWriter
,
await
HandleHttpSessionRequest
(
endPoint
,
clientConnection
,
clientStream
,
clientStreamWriter
,
cancellationTokenSource
,
connectHostname
,
connectArgs
?.
WebSession
.
ConnectRequest
);
cancellationTokenSource
,
connectHostname
,
connectArgs
?.
WebSession
.
ConnectRequest
);
}
}
...
...
Titanium.Web.Proxy/Helpers/HttpHelper.cs
View file @
a8497ab2
...
@@ -21,13 +21,13 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -21,13 +21,13 @@ namespace Titanium.Web.Proxy.Helpers
{
{
try
try
{
{
//return default if not specified
//
return default if not specified
if
(
contentType
==
null
)
if
(
contentType
==
null
)
{
{
return
defaultEncoding
;
return
defaultEncoding
;
}
}
//extract the encoding by finding the charset
//
extract the encoding by finding the charset
var
parameters
=
contentType
.
Split
(
ProxyConstants
.
SemiColonSplit
);
var
parameters
=
contentType
.
Split
(
ProxyConstants
.
SemiColonSplit
);
foreach
(
string
parameter
in
parameters
)
foreach
(
string
parameter
in
parameters
)
{
{
...
@@ -51,11 +51,11 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -51,11 +51,11 @@ namespace Titanium.Web.Proxy.Helpers
}
}
catch
catch
{
{
//parsing errors
//
parsing errors
// ignored
// ignored
}
}
//return default if not specified
//
return default if not specified
return
defaultEncoding
;
return
defaultEncoding
;
}
}
...
@@ -63,7 +63,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -63,7 +63,7 @@ namespace Titanium.Web.Proxy.Helpers
{
{
if
(
contentType
!=
null
)
if
(
contentType
!=
null
)
{
{
//extract the boundary
//
extract the boundary
var
parameters
=
contentType
.
Split
(
ProxyConstants
.
SemiColonSplit
);
var
parameters
=
contentType
.
Split
(
ProxyConstants
.
SemiColonSplit
);
foreach
(
string
parameter
in
parameters
)
foreach
(
string
parameter
in
parameters
)
{
{
...
@@ -81,7 +81,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -81,7 +81,7 @@ namespace Titanium.Web.Proxy.Helpers
}
}
}
}
//return null if not specified
//
return null if not specified
return
null
;
return
null
;
}
}
...
@@ -94,14 +94,14 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -94,14 +94,14 @@ namespace Titanium.Web.Proxy.Helpers
/// <returns></returns>
/// <returns></returns>
internal
static
string
GetWildCardDomainName
(
string
hostname
)
internal
static
string
GetWildCardDomainName
(
string
hostname
)
{
{
//only for subdomains we need wild card
//
only for subdomains we need wild card
//example www.google.com or gstatic.google.com
//
example www.google.com or gstatic.google.com
//but NOT for google.com
//
but NOT for google.com
if
(
hostname
.
Split
(
ProxyConstants
.
DotSplit
).
Length
>
2
)
if
(
hostname
.
Split
(
ProxyConstants
.
DotSplit
).
Length
>
2
)
{
{
int
idx
=
hostname
.
IndexOf
(
ProxyConstants
.
DotSplit
);
int
idx
=
hostname
.
IndexOf
(
ProxyConstants
.
DotSplit
);
//issue #352
//
issue #352
if
(
hostname
.
Substring
(
0
,
idx
).
Contains
(
"-"
))
if
(
hostname
.
Substring
(
0
,
idx
).
Contains
(
"-"
))
{
{
return
hostname
;
return
hostname
;
...
@@ -111,7 +111,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -111,7 +111,7 @@ namespace Titanium.Web.Proxy.Helpers
return
"*."
+
rootDomain
;
return
"*."
+
rootDomain
;
}
}
//return as it is
//
return as it is
return
hostname
;
return
hostname
;
}
}
...
...
Titanium.Web.Proxy/Helpers/HttpWriter.cs
View file @
a8497ab2
...
@@ -165,19 +165,19 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -165,19 +165,19 @@ namespace Titanium.Web.Proxy.Helpers
internal
Task
CopyBodyAsync
(
ICustomStreamReader
streamReader
,
bool
isChunked
,
long
contentLength
,
internal
Task
CopyBodyAsync
(
ICustomStreamReader
streamReader
,
bool
isChunked
,
long
contentLength
,
Action
<
byte
[],
int
,
int
>
onCopy
,
CancellationToken
cancellationToken
)
Action
<
byte
[],
int
,
int
>
onCopy
,
CancellationToken
cancellationToken
)
{
{
//For chunked request we need to read data as they arrive, until we reach a chunk end symbol
//
For chunked request we need to read data as they arrive, until we reach a chunk end symbol
if
(
isChunked
)
if
(
isChunked
)
{
{
return
CopyBodyChunkedAsync
(
streamReader
,
onCopy
,
cancellationToken
);
return
CopyBodyChunkedAsync
(
streamReader
,
onCopy
,
cancellationToken
);
}
}
//http 1.0 or the stream reader limits the stream
//
http 1.0 or the stream reader limits the stream
if
(
contentLength
==
-
1
)
if
(
contentLength
==
-
1
)
{
{
contentLength
=
long
.
MaxValue
;
contentLength
=
long
.
MaxValue
;
}
}
//If not chunked then its easy just read the amount of bytes mentioned in content length header
//
If not chunked then its easy just read the amount of bytes mentioned in content length header
return
CopyBytesFromStream
(
streamReader
,
contentLength
,
onCopy
,
cancellationToken
);
return
CopyBytesFromStream
(
streamReader
,
contentLength
,
onCopy
,
cancellationToken
);
}
}
...
@@ -230,7 +230,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -230,7 +230,7 @@ namespace Titanium.Web.Proxy.Helpers
await
WriteLineAsync
(
cancellationToken
);
await
WriteLineAsync
(
cancellationToken
);
//chunk trail
//
chunk trail
await
reader
.
ReadLineAsync
(
cancellationToken
);
await
reader
.
ReadLineAsync
(
cancellationToken
);
if
(
chunkSize
==
0
)
if
(
chunkSize
==
0
)
...
...
Titanium.Web.Proxy/Helpers/SystemProxy.cs
View file @
a8497ab2
...
@@ -66,7 +66,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -66,7 +66,7 @@ namespace Titanium.Web.Proxy.Helpers
return
false
;
return
false
;
};
};
//On Console exit make sure we also exit the proxy
//
On Console exit make sure we also exit the proxy
NativeMethods
.
SetConsoleCtrlHandler
(
NativeMethods
.
Handler
,
true
);
NativeMethods
.
SetConsoleCtrlHandler
(
NativeMethods
.
Handler
,
true
);
}
}
}
}
...
...
Titanium.Web.Proxy/Helpers/Tcp.cs
View file @
a8497ab2
...
@@ -115,7 +115,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -115,7 +115,7 @@ namespace Titanium.Web.Proxy.Helpers
var
taskCompletionSource
=
new
TaskCompletionSource
<
bool
>();
var
taskCompletionSource
=
new
TaskCompletionSource
<
bool
>();
cancellationTokenSource
.
Token
.
Register
(()
=>
taskCompletionSource
.
TrySetResult
(
true
));
cancellationTokenSource
.
Token
.
Register
(()
=>
taskCompletionSource
.
TrySetResult
(
true
));
//Now async relay all server=>client & client=>server data
//
Now async relay all server=>client & client=>server data
var
clientBuffer
=
BufferPool
.
GetBuffer
(
bufferSize
);
var
clientBuffer
=
BufferPool
.
GetBuffer
(
bufferSize
);
var
serverBuffer
=
BufferPool
.
GetBuffer
(
bufferSize
);
var
serverBuffer
=
BufferPool
.
GetBuffer
(
bufferSize
);
try
try
...
@@ -217,7 +217,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -217,7 +217,7 @@ namespace Titanium.Web.Proxy.Helpers
CancellationTokenSource
cancellationTokenSource
,
CancellationTokenSource
cancellationTokenSource
,
ExceptionHandler
exceptionFunc
)
ExceptionHandler
exceptionFunc
)
{
{
//Now async relay all server=>client & client=>server data
//
Now async relay all server=>client & client=>server data
var
sendRelay
=
var
sendRelay
=
clientStream
.
CopyToAsync
(
serverStream
,
onDataSend
,
bufferSize
,
cancellationTokenSource
.
Token
);
clientStream
.
CopyToAsync
(
serverStream
,
onDataSend
,
bufferSize
,
cancellationTokenSource
.
Token
);
var
receiveRelay
=
var
receiveRelay
=
...
@@ -273,7 +273,7 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -273,7 +273,7 @@ namespace Titanium.Web.Proxy.Helpers
CancellationTokenSource
cancellationTokenSource
,
Guid
connectionId
,
CancellationTokenSource
cancellationTokenSource
,
Guid
connectionId
,
ExceptionHandler
exceptionFunc
)
ExceptionHandler
exceptionFunc
)
{
{
//Now async relay all server=>client & client=>server data
//
Now async relay all server=>client & client=>server data
var
sendRelay
=
var
sendRelay
=
CopyHttp2FrameAsync
(
clientStream
,
serverStream
,
onDataSend
,
bufferSize
,
connectionId
,
CopyHttp2FrameAsync
(
clientStream
,
serverStream
,
onDataSend
,
bufferSize
,
connectionId
,
cancellationTokenSource
.
Token
);
cancellationTokenSource
.
Token
);
...
...
Titanium.Web.Proxy/Http/HeaderCollection.cs
View file @
a8497ab2
...
@@ -296,7 +296,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -296,7 +296,7 @@ namespace Titanium.Web.Proxy.Http
/// </summary>
/// </summary>
internal
void
FixProxyHeaders
()
internal
void
FixProxyHeaders
()
{
{
//If proxy-connection close was returned inform to close the connection
//
If proxy-connection close was returned inform to close the connection
string
proxyHeader
=
GetHeaderValueOrNull
(
KnownHeaders
.
ProxyConnection
);
string
proxyHeader
=
GetHeaderValueOrNull
(
KnownHeaders
.
ProxyConnection
);
RemoveHeader
(
KnownHeaders
.
ProxyConnection
);
RemoveHeader
(
KnownHeaders
.
ProxyConnection
);
...
...
Titanium.Web.Proxy/Http/HttpWebClient.cs
View file @
a8497ab2
...
@@ -89,13 +89,13 @@ namespace Titanium.Web.Proxy.Http
...
@@ -89,13 +89,13 @@ namespace Titanium.Web.Proxy.Http
var
writer
=
ServerConnection
.
StreamWriter
;
var
writer
=
ServerConnection
.
StreamWriter
;
//prepare the request & headers
//
prepare the request & headers
await
writer
.
WriteLineAsync
(
Request
.
CreateRequestLine
(
Request
.
Method
,
await
writer
.
WriteLineAsync
(
Request
.
CreateRequestLine
(
Request
.
Method
,
useUpstreamProxy
||
isTransparent
?
Request
.
OriginalUrl
:
Request
.
RequestUri
.
PathAndQuery
,
useUpstreamProxy
||
isTransparent
?
Request
.
OriginalUrl
:
Request
.
RequestUri
.
PathAndQuery
,
Request
.
HttpVersion
),
cancellationToken
);
Request
.
HttpVersion
),
cancellationToken
);
//Send Authentication to Upstream proxy if needed
//
Send Authentication to Upstream proxy if needed
if
(!
isTransparent
&&
upstreamProxy
!=
null
if
(!
isTransparent
&&
upstreamProxy
!=
null
&&
ServerConnection
.
IsHttps
==
false
&&
ServerConnection
.
IsHttps
==
false
&&
!
string
.
IsNullOrEmpty
(
upstreamProxy
.
UserName
)
&&
!
string
.
IsNullOrEmpty
(
upstreamProxy
.
UserName
)
...
@@ -106,7 +106,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -106,7 +106,7 @@ namespace Titanium.Web.Proxy.Http
.
WriteToStreamAsync
(
writer
,
cancellationToken
);
.
WriteToStreamAsync
(
writer
,
cancellationToken
);
}
}
//write request headers
//
write request headers
foreach
(
var
header
in
Request
.
Headers
)
foreach
(
var
header
in
Request
.
Headers
)
{
{
if
(
isTransparent
||
header
.
Name
!=
KnownHeaders
.
ProxyAuthorization
)
if
(
isTransparent
||
header
.
Name
!=
KnownHeaders
.
ProxyAuthorization
)
...
@@ -126,7 +126,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -126,7 +126,7 @@ namespace Titanium.Web.Proxy.Http
Response
.
ParseResponseLine
(
httpStatus
,
out
_
,
out
int
responseStatusCode
,
Response
.
ParseResponseLine
(
httpStatus
,
out
_
,
out
int
responseStatusCode
,
out
string
responseStatusDescription
);
out
string
responseStatusDescription
);
//find if server is willing for expect continue
//
find if server is willing for expect continue
if
(
responseStatusCode
==
(
int
)
HttpStatusCode
.
Continue
if
(
responseStatusCode
==
(
int
)
HttpStatusCode
.
Continue
&&
responseStatusDescription
.
EqualsIgnoreCase
(
"continue"
))
&&
responseStatusDescription
.
EqualsIgnoreCase
(
"continue"
))
{
{
...
@@ -149,7 +149,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -149,7 +149,7 @@ namespace Titanium.Web.Proxy.Http
/// <returns></returns>
/// <returns></returns>
internal
async
Task
ReceiveResponse
(
CancellationToken
cancellationToken
)
internal
async
Task
ReceiveResponse
(
CancellationToken
cancellationToken
)
{
{
//return if this is already read
//
return if this is already read
if
(
Response
.
StatusCode
!=
0
)
if
(
Response
.
StatusCode
!=
0
)
{
{
return
;
return
;
...
@@ -172,16 +172,16 @@ namespace Titanium.Web.Proxy.Http
...
@@ -172,16 +172,16 @@ namespace Titanium.Web.Proxy.Http
Response
.
StatusCode
=
statusCode
;
Response
.
StatusCode
=
statusCode
;
Response
.
StatusDescription
=
statusDescription
;
Response
.
StatusDescription
=
statusDescription
;
//For HTTP 1.1 comptibility server may send expect-continue even if not asked for it in request
//
For HTTP 1.1 comptibility server may send expect-continue even if not asked for it in request
if
(
Response
.
StatusCode
==
(
int
)
HttpStatusCode
.
Continue
if
(
Response
.
StatusCode
==
(
int
)
HttpStatusCode
.
Continue
&&
Response
.
StatusDescription
.
EqualsIgnoreCase
(
"continue"
))
&&
Response
.
StatusDescription
.
EqualsIgnoreCase
(
"continue"
))
{
{
//Read the next line after 100-continue
//
Read the next line after 100-continue
Response
.
Is100Continue
=
true
;
Response
.
Is100Continue
=
true
;
Response
.
StatusCode
=
0
;
Response
.
StatusCode
=
0
;
await
ServerConnection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
await
ServerConnection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
//now receive response
//
now receive response
await
ReceiveResponse
(
cancellationToken
);
await
ReceiveResponse
(
cancellationToken
);
return
;
return
;
}
}
...
@@ -189,17 +189,17 @@ namespace Titanium.Web.Proxy.Http
...
@@ -189,17 +189,17 @@ namespace Titanium.Web.Proxy.Http
if
(
Response
.
StatusCode
==
(
int
)
HttpStatusCode
.
ExpectationFailed
if
(
Response
.
StatusCode
==
(
int
)
HttpStatusCode
.
ExpectationFailed
&&
Response
.
StatusDescription
.
EqualsIgnoreCase
(
"expectation failed"
))
&&
Response
.
StatusDescription
.
EqualsIgnoreCase
(
"expectation failed"
))
{
{
//read next line after expectation failed response
//
read next line after expectation failed response
Response
.
ExpectationFailed
=
true
;
Response
.
ExpectationFailed
=
true
;
Response
.
StatusCode
=
0
;
Response
.
StatusCode
=
0
;
await
ServerConnection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
await
ServerConnection
.
Stream
.
ReadLineAsync
(
cancellationToken
);
//now receive response
//
now receive response
await
ReceiveResponse
(
cancellationToken
);
await
ReceiveResponse
(
cancellationToken
);
return
;
return
;
}
}
//Read the response headers in to unique and non-unique header collections
//
Read the response headers in to unique and non-unique header collections
await
HeaderParser
.
ReadHeaders
(
ServerConnection
.
Stream
,
Response
.
Headers
,
cancellationToken
);
await
HeaderParser
.
ReadHeaders
(
ServerConnection
.
Stream
,
Response
.
Headers
,
cancellationToken
);
}
}
...
...
Titanium.Web.Proxy/Http/Request.cs
View file @
a8497ab2
...
@@ -43,19 +43,19 @@ namespace Titanium.Web.Proxy.Http
...
@@ -43,19 +43,19 @@ namespace Titanium.Web.Proxy.Http
{
{
long
contentLength
=
ContentLength
;
long
contentLength
=
ContentLength
;
//If content length is set to 0 the request has no body
//
If content length is set to 0 the request has no body
if
(
contentLength
==
0
)
if
(
contentLength
==
0
)
{
{
return
false
;
return
false
;
}
}
//Has body only if request is chunked or content length >0
//
Has body only if request is chunked or content length >0
if
(
IsChunked
||
contentLength
>
0
)
if
(
IsChunked
||
contentLength
>
0
)
{
{
return
true
;
return
true
;
}
}
//has body if POST and when version is http/1.0
//
has body if POST and when version is http/1.0
if
(
Method
==
"POST"
&&
HttpVersion
==
HttpHeader
.
Version10
)
if
(
Method
==
"POST"
&&
HttpVersion
==
HttpHeader
.
Version10
)
{
{
return
true
;
return
true
;
...
@@ -157,7 +157,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -157,7 +157,7 @@ namespace Titanium.Web.Proxy.Http
return
;
return
;
}
}
//GET request don't have a request body to read
//
GET request don't have a request body to read
if
(!
HasBody
)
if
(!
HasBody
)
{
{
throw
new
BodyNotFoundException
(
"Request don't have a body. "
+
throw
new
BodyNotFoundException
(
"Request don't have a body. "
+
...
@@ -189,7 +189,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -189,7 +189,7 @@ namespace Titanium.Web.Proxy.Http
internal
static
void
ParseRequestLine
(
string
httpCmd
,
out
string
httpMethod
,
out
string
httpUrl
,
internal
static
void
ParseRequestLine
(
string
httpCmd
,
out
string
httpMethod
,
out
string
httpUrl
,
out
Version
version
)
out
Version
version
)
{
{
//break up the line into three components (method, remote URL & Http Version)
//
break up the line into three components (method, remote URL & Http Version)
var
httpCmdSplit
=
httpCmd
.
Split
(
ProxyConstants
.
SpaceSplit
,
3
);
var
httpCmdSplit
=
httpCmd
.
Split
(
ProxyConstants
.
SpaceSplit
,
3
);
if
(
httpCmdSplit
.
Length
<
2
)
if
(
httpCmdSplit
.
Length
<
2
)
...
@@ -197,7 +197,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -197,7 +197,7 @@ namespace Titanium.Web.Proxy.Http
throw
new
Exception
(
"Invalid HTTP request line: "
+
httpCmd
);
throw
new
Exception
(
"Invalid HTTP request line: "
+
httpCmd
);
}
}
//Find the request Verb
//
Find the request Verb
httpMethod
=
httpCmdSplit
[
0
];
httpMethod
=
httpCmdSplit
[
0
];
if
(!
IsAllUpper
(
httpMethod
))
if
(!
IsAllUpper
(
httpMethod
))
{
{
...
@@ -206,7 +206,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -206,7 +206,7 @@ namespace Titanium.Web.Proxy.Http
httpUrl
=
httpCmdSplit
[
1
];
httpUrl
=
httpCmdSplit
[
1
];
//parse the HTTP version
//
parse the HTTP version
version
=
HttpHeader
.
Version11
;
version
=
HttpHeader
.
Version11
;
if
(
httpCmdSplit
.
Length
==
3
)
if
(
httpCmdSplit
.
Length
==
3
)
{
{
...
...
Titanium.Web.Proxy/Http/RequestResponseBase.cs
View file @
a8497ab2
...
@@ -140,7 +140,7 @@ namespace Titanium.Web.Proxy.Http
...
@@ -140,7 +140,7 @@ namespace Titanium.Web.Proxy.Http
BodyInternal
=
value
;
BodyInternal
=
value
;
bodyString
=
null
;
bodyString
=
null
;
//If there is a content length header update it
//
If there is a content length header update it
UpdateContentLength
();
UpdateContentLength
();
}
}
}
}
...
...
Titanium.Web.Proxy/Http/Response.cs
View file @
a8497ab2
...
@@ -47,21 +47,21 @@ namespace Titanium.Web.Proxy.Http
...
@@ -47,21 +47,21 @@ namespace Titanium.Web.Proxy.Http
{
{
long
contentLength
=
ContentLength
;
long
contentLength
=
ContentLength
;
//If content length is set to 0 the response has no body
//
If content length is set to 0 the response has no body
if
(
contentLength
==
0
)
if
(
contentLength
==
0
)
{
{
return
false
;
return
false
;
}
}
//Has body only if response is chunked or content length >0
//
Has body only if response is chunked or content length >0
//If none are true then check if connection:close header exist, if so write response until server or client terminates the connection
//
If none are true then check if connection:close header exist, if so write response until server or client terminates the connection
if
(
IsChunked
||
contentLength
>
0
||
!
KeepAlive
)
if
(
IsChunked
||
contentLength
>
0
||
!
KeepAlive
)
{
{
return
true
;
return
true
;
}
}
//has response if connection:keep-alive header exist and when version is http/1.0
//
has 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)
//
Because in Http 1.0 server can return a response without content-length (expectation being client would read until end of stream)
if
(
KeepAlive
&&
HttpVersion
==
HttpHeader
.
Version10
)
if
(
KeepAlive
&&
HttpVersion
==
HttpHeader
.
Version10
)
{
{
return
true
;
return
true
;
...
...
Titanium.Web.Proxy/Http/Responses/GenericResponse.cs
View file @
a8497ab2
...
@@ -19,8 +19,8 @@ namespace Titanium.Web.Proxy.Http.Responses
...
@@ -19,8 +19,8 @@ namespace Titanium.Web.Proxy.Http.Responses
#if NET45
#if NET45
StatusDescription
=
HttpWorkerRequest
.
GetStatusDescription
(
StatusCode
);
StatusDescription
=
HttpWorkerRequest
.
GetStatusDescription
(
StatusCode
);
#else
#else
//todo: this is not really correct, status description should contain spaces, too
//
todo: this is not really correct, status description should contain spaces, too
//see: https://tools.ietf.org/html/rfc7231#section-6.1
//
see: https://tools.ietf.org/html/rfc7231#section-6.1
StatusDescription
=
status
.
ToString
();
StatusDescription
=
status
.
ToString
();
#endif
#endif
}
}
...
...
Titanium.Web.Proxy/Network/Certificate/BCCertificateMaker.cs
View file @
a8497ab2
...
@@ -95,7 +95,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
...
@@ -95,7 +95,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
if
(
hostName
!=
null
)
if
(
hostName
!=
null
)
{
{
//add subject alternative names
//
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
);
var
subjectAlternativeNamesExtension
=
new
DerSequence
(
subjectAlternativeNames
);
...
...
Titanium.Web.Proxy/Network/Certificate/WinCertificateMaker.cs
View file @
a8497ab2
...
@@ -64,7 +64,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
...
@@ -64,7 +64,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
typeSignerCertificate
=
Type
.
GetTypeFromProgID
(
"X509Enrollment.CSignerCertificate"
);
typeSignerCertificate
=
Type
.
GetTypeFromProgID
(
"X509Enrollment.CSignerCertificate"
);
typeX509Enrollment
=
Type
.
GetTypeFromProgID
(
"X509Enrollment.CX509Enrollment"
);
typeX509Enrollment
=
Type
.
GetTypeFromProgID
(
"X509Enrollment.CX509Enrollment"
);
//for alternative names
//
for alternative names
typeAltNamesCollection
=
Type
.
GetTypeFromProgID
(
"X509Enrollment.CAlternativeNames"
);
typeAltNamesCollection
=
Type
.
GetTypeFromProgID
(
"X509Enrollment.CAlternativeNames"
);
typeExtNames
=
Type
.
GetTypeFromProgID
(
"X509Enrollment.CX509ExtensionAlternativeNames"
);
typeExtNames
=
Type
.
GetTypeFromProgID
(
"X509Enrollment.CX509ExtensionAlternativeNames"
);
typeCAlternativeName
=
Type
.
GetTypeFromProgID
(
"X509Enrollment.CAlternativeName"
);
typeCAlternativeName
=
Type
.
GetTypeFromProgID
(
"X509Enrollment.CAlternativeName"
);
...
@@ -192,7 +192,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
...
@@ -192,7 +192,7 @@ namespace Titanium.Web.Proxy.Network.Certificate
if
(!
isRoot
)
if
(!
isRoot
)
{
{
//add alternative names
//
add alternative names
// https://forums.iis.net/t/1180823.aspx
// https://forums.iis.net/t/1180823.aspx
var
altNameCollection
=
Activator
.
CreateInstance
(
typeAltNamesCollection
);
var
altNameCollection
=
Activator
.
CreateInstance
(
typeAltNamesCollection
);
...
@@ -284,15 +284,19 @@ namespace Titanium.Web.Proxy.Network.Certificate
...
@@ -284,15 +284,19 @@ namespace Titanium.Web.Proxy.Network.Certificate
cancellationToken
).
Result
;
cancellationToken
).
Result
;
}
}
//Subject
//
Subject
string
fullSubject
=
$"CN=
{
sSubjectCN
}
"
;
string
fullSubject
=
$"CN=
{
sSubjectCN
}
"
;
//Sig Algo
// Sig Algo
const
string
hashAlgo
=
"SHA256"
;
const
string
hashAlgo
=
"SHA256"
;
//Grace Days
// Grace Days
const
int
graceDays
=
-
366
;
const
int
graceDays
=
-
366
;
//ValiDays
// ValiDays
const
int
validDays
=
1825
;
const
int
validDays
=
1825
;
//KeyLength
// KeyLength
const
int
keyLength
=
2048
;
const
int
keyLength
=
2048
;
var
graceTime
=
DateTime
.
Now
.
AddDays
(
graceDays
);
var
graceTime
=
DateTime
.
Now
.
AddDays
(
graceDays
);
...
...
Titanium.Web.Proxy/Network/CertificateManager.cs
View file @
a8497ab2
...
@@ -141,7 +141,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -141,7 +141,7 @@ namespace Titanium.Web.Proxy.Network
get
=>
engine
;
get
=>
engine
;
set
set
{
{
//For Mono (or Non-Windows) only Bouncy Castle is supported
//
For Mono (or Non-Windows) only Bouncy Castle is supported
if
(!
RunTime
.
IsWindows
||
RunTime
.
IsRunningOnMono
)
if
(!
RunTime
.
IsWindows
||
RunTime
.
IsRunningOnMono
)
{
{
value
=
CertificateEngine
.
BouncyCastle
;
value
=
CertificateEngine
.
BouncyCastle
;
...
@@ -333,8 +333,8 @@ namespace Titanium.Web.Proxy.Network
...
@@ -333,8 +333,8 @@ namespace Titanium.Web.Proxy.Network
var
x509Store
=
new
X509Store
(
storeName
,
storeLocation
);
var
x509Store
=
new
X509Store
(
storeName
,
storeLocation
);
//
TODO
//
todo
//also it should do not duplicate if certificate already exists
//
also it should do not duplicate if certificate already exists
try
try
{
{
x509Store
.
Open
(
OpenFlags
.
ReadWrite
);
x509Store
.
Open
(
OpenFlags
.
ReadWrite
);
...
@@ -428,7 +428,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -428,7 +428,7 @@ namespace Titanium.Web.Proxy.Network
{
{
certificate
=
MakeCertificate
(
certificateName
,
false
);
certificate
=
MakeCertificate
(
certificateName
,
false
);
//store as cache
//
store as cache
Task
.
Run
(()
=>
Task
.
Run
(()
=>
{
{
try
try
...
@@ -447,7 +447,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -447,7 +447,7 @@ namespace Titanium.Web.Proxy.Network
{
{
certificate
=
new
X509Certificate2
(
certificatePath
,
string
.
Empty
,
StorageFlag
);
certificate
=
new
X509Certificate2
(
certificatePath
,
string
.
Empty
,
StorageFlag
);
}
}
//if load failed create again
//
if load failed create again
catch
catch
{
{
certificate
=
MakeCertificate
(
certificateName
,
false
);
certificate
=
MakeCertificate
(
certificateName
,
false
);
...
@@ -474,21 +474,21 @@ namespace Titanium.Web.Proxy.Network
...
@@ -474,21 +474,21 @@ namespace Titanium.Web.Proxy.Network
/// <returns></returns>
/// <returns></returns>
internal
async
Task
<
X509Certificate2
>
CreateCertificateAsync
(
string
certificateName
)
internal
async
Task
<
X509Certificate2
>
CreateCertificateAsync
(
string
certificateName
)
{
{
//check in cache first
//
check in cache first
if
(
certificateCache
.
TryGetValue
(
certificateName
,
out
var
cached
))
if
(
certificateCache
.
TryGetValue
(
certificateName
,
out
var
cached
))
{
{
cached
.
LastAccess
=
DateTime
.
Now
;
cached
.
LastAccess
=
DateTime
.
Now
;
return
cached
.
Certificate
;
return
cached
.
Certificate
;
}
}
//handle burst requests with same certificate name
//
handle burst requests with same certificate name
//by checking for existing task for same certificate name
//
by checking for existing task for same certificate name
if
(
pendingCertificateCreationTasks
.
TryGetValue
(
certificateName
,
out
var
task
))
if
(
pendingCertificateCreationTasks
.
TryGetValue
(
certificateName
,
out
var
task
))
{
{
return
await
task
;
return
await
task
;
}
}
//run certificate creation task & add it to pending tasks
//
run certificate creation task & add it to pending tasks
task
=
Task
.
Run
(()
=>
task
=
Task
.
Run
(()
=>
{
{
var
result
=
CreateCertificate
(
certificateName
,
false
);
var
result
=
CreateCertificate
(
certificateName
,
false
);
...
@@ -504,7 +504,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -504,7 +504,7 @@ namespace Titanium.Web.Proxy.Network
});
});
pendingCertificateCreationTasks
.
TryAdd
(
certificateName
,
task
);
pendingCertificateCreationTasks
.
TryAdd
(
certificateName
,
task
);
//cleanup pending tasks & return result
//
cleanup pending tasks & return result
var
certificate
=
await
task
;
var
certificate
=
await
task
;
pendingCertificateCreationTasks
.
TryRemove
(
certificateName
,
out
task
);
pendingCertificateCreationTasks
.
TryRemove
(
certificateName
,
out
task
);
...
@@ -528,7 +528,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -528,7 +528,7 @@ namespace Titanium.Web.Proxy.Network
certificateCache
.
TryRemove
(
cache
.
Key
,
out
_
);
certificateCache
.
TryRemove
(
cache
.
Key
,
out
_
);
}
}
//after a minute come back to check for outdated certificates in cache
//
after a minute come back to check for outdated certificates in cache
await
Task
.
Delay
(
1000
*
60
);
await
Task
.
Delay
(
1000
*
60
);
}
}
}
}
...
@@ -659,20 +659,20 @@ namespace Titanium.Web.Proxy.Network
...
@@ -659,20 +659,20 @@ namespace Titanium.Web.Proxy.Network
/// </summary>
/// </summary>
public
void
TrustRootCertificate
(
bool
machineTrusted
=
false
)
public
void
TrustRootCertificate
(
bool
machineTrusted
=
false
)
{
{
//currentUser\personal
//
currentUser\personal
InstallCertificate
(
StoreName
.
My
,
StoreLocation
.
CurrentUser
);
InstallCertificate
(
StoreName
.
My
,
StoreLocation
.
CurrentUser
);
if
(!
machineTrusted
)
if
(!
machineTrusted
)
{
{
//currentUser\Root
//
currentUser\Root
InstallCertificate
(
StoreName
.
Root
,
StoreLocation
.
CurrentUser
);
InstallCertificate
(
StoreName
.
Root
,
StoreLocation
.
CurrentUser
);
}
}
else
else
{
{
//current system
//
current system
InstallCertificate
(
StoreName
.
My
,
StoreLocation
.
LocalMachine
);
InstallCertificate
(
StoreName
.
My
,
StoreLocation
.
LocalMachine
);
//this adds to both currentUser\Root & currentMachine\Root
//
this adds to both currentUser\Root & currentMachine\Root
InstallCertificate
(
StoreName
.
Root
,
StoreLocation
.
LocalMachine
);
InstallCertificate
(
StoreName
.
Root
,
StoreLocation
.
LocalMachine
);
}
}
}
}
...
@@ -689,13 +689,13 @@ namespace Titanium.Web.Proxy.Network
...
@@ -689,13 +689,13 @@ namespace Titanium.Web.Proxy.Network
return
false
;
return
false
;
}
}
//currentUser\Personal
//
currentUser\Personal
InstallCertificate
(
StoreName
.
My
,
StoreLocation
.
CurrentUser
);
InstallCertificate
(
StoreName
.
My
,
StoreLocation
.
CurrentUser
);
string
pfxFileName
=
Path
.
GetTempFileName
();
string
pfxFileName
=
Path
.
GetTempFileName
();
File
.
WriteAllBytes
(
pfxFileName
,
RootCertificate
.
Export
(
X509ContentType
.
Pkcs12
,
PfxPassword
));
File
.
WriteAllBytes
(
pfxFileName
,
RootCertificate
.
Export
(
X509ContentType
.
Pkcs12
,
PfxPassword
));
//currentUser\Root, currentMachine\Personal & currentMachine\Root
//
currentUser\Root, currentMachine\Personal & currentMachine\Root
var
info
=
new
ProcessStartInfo
var
info
=
new
ProcessStartInfo
{
{
FileName
=
"certutil.exe"
,
FileName
=
"certutil.exe"
,
...
@@ -804,20 +804,20 @@ namespace Titanium.Web.Proxy.Network
...
@@ -804,20 +804,20 @@ namespace Titanium.Web.Proxy.Network
/// <param name="machineTrusted">Should also remove from machine store?</param>
/// <param name="machineTrusted">Should also remove from machine store?</param>
public
void
RemoveTrustedRootCertificate
(
bool
machineTrusted
=
false
)
public
void
RemoveTrustedRootCertificate
(
bool
machineTrusted
=
false
)
{
{
//currentUser\personal
//
currentUser\personal
UninstallCertificate
(
StoreName
.
My
,
StoreLocation
.
CurrentUser
,
RootCertificate
);
UninstallCertificate
(
StoreName
.
My
,
StoreLocation
.
CurrentUser
,
RootCertificate
);
if
(!
machineTrusted
)
if
(!
machineTrusted
)
{
{
//currentUser\Root
//
currentUser\Root
UninstallCertificate
(
StoreName
.
Root
,
StoreLocation
.
CurrentUser
,
RootCertificate
);
UninstallCertificate
(
StoreName
.
Root
,
StoreLocation
.
CurrentUser
,
RootCertificate
);
}
}
else
else
{
{
//current system
//
current system
UninstallCertificate
(
StoreName
.
My
,
StoreLocation
.
LocalMachine
,
RootCertificate
);
UninstallCertificate
(
StoreName
.
My
,
StoreLocation
.
LocalMachine
,
RootCertificate
);
//this adds to both currentUser\Root & currentMachine\Root
//
this adds to both currentUser\Root & currentMachine\Root
UninstallCertificate
(
StoreName
.
Root
,
StoreLocation
.
LocalMachine
,
RootCertificate
);
UninstallCertificate
(
StoreName
.
Root
,
StoreLocation
.
LocalMachine
,
RootCertificate
);
}
}
}
}
...
@@ -833,7 +833,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -833,7 +833,7 @@ namespace Titanium.Web.Proxy.Network
return
false
;
return
false
;
}
}
//currentUser\Personal
//
currentUser\Personal
UninstallCertificate
(
StoreName
.
My
,
StoreLocation
.
CurrentUser
,
RootCertificate
);
UninstallCertificate
(
StoreName
.
My
,
StoreLocation
.
CurrentUser
,
RootCertificate
);
var
infos
=
new
List
<
ProcessStartInfo
>();
var
infos
=
new
List
<
ProcessStartInfo
>();
...
@@ -855,7 +855,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -855,7 +855,7 @@ namespace Titanium.Web.Proxy.Network
infos
.
AddRange
(
infos
.
AddRange
(
new
List
<
ProcessStartInfo
>
new
List
<
ProcessStartInfo
>
{
{
//currentMachine\Personal
//
currentMachine\Personal
new
ProcessStartInfo
new
ProcessStartInfo
{
{
FileName
=
"certutil.exe"
,
FileName
=
"certutil.exe"
,
...
@@ -866,7 +866,7 @@ namespace Titanium.Web.Proxy.Network
...
@@ -866,7 +866,7 @@ namespace Titanium.Web.Proxy.Network
ErrorDialog
=
false
,
ErrorDialog
=
false
,
WindowStyle
=
ProcessWindowStyle
.
Hidden
WindowStyle
=
ProcessWindowStyle
.
Hidden
},
},
//currentUser\Personal & currentMachine\Personal
//
currentUser\Personal & currentMachine\Personal
new
ProcessStartInfo
new
ProcessStartInfo
{
{
FileName
=
"certutil.exe"
,
FileName
=
"certutil.exe"
,
...
...
Titanium.Web.Proxy/Network/Tcp/TcpConnectionFactory.cs
View file @
a8497ab2
...
@@ -39,13 +39,13 @@ namespace Titanium.Web.Proxy.Network.Tcp
...
@@ -39,13 +39,13 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
{
bool
useUpstreamProxy
=
false
;
bool
useUpstreamProxy
=
false
;
//check if external proxy is set for HTTP/HTTPS
//
check if external proxy is set for HTTP/HTTPS
if
(
externalProxy
!=
null
&&
if
(
externalProxy
!=
null
&&
!(
externalProxy
.
HostName
==
remoteHostName
&&
externalProxy
.
Port
==
remotePort
))
!(
externalProxy
.
HostName
==
remoteHostName
&&
externalProxy
.
Port
==
remotePort
))
{
{
useUpstreamProxy
=
true
;
useUpstreamProxy
=
true
;
//check if we need to ByPass
//
check if we need to ByPass
if
(
externalProxy
.
BypassLocalhost
&&
NetworkHelper
.
IsLocalIpAddress
(
remoteHostName
))
if
(
externalProxy
.
BypassLocalhost
&&
NetworkHelper
.
IsLocalIpAddress
(
remoteHostName
))
{
{
useUpstreamProxy
=
false
;
useUpstreamProxy
=
false
;
...
@@ -61,7 +61,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
...
@@ -61,7 +61,7 @@ namespace Titanium.Web.Proxy.Network.Tcp
{
{
tcpClient
=
new
TcpClient
(
upStreamEndPoint
);
tcpClient
=
new
TcpClient
(
upStreamEndPoint
);
//If this proxy uses another external proxy then create a tunnel request for HTTP/HTTPS connections
//
If this proxy uses another external proxy then create a tunnel request for HTTP/HTTPS connections
if
(
useUpstreamProxy
)
if
(
useUpstreamProxy
)
{
{
await
tcpClient
.
ConnectAsync
(
externalProxy
.
HostName
,
externalProxy
.
Port
);
await
tcpClient
.
ConnectAsync
(
externalProxy
.
HostName
,
externalProxy
.
Port
);
...
...
Titanium.Web.Proxy/Network/WinAuth/Security/Common.cs
View file @
a8497ab2
...
@@ -173,7 +173,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
...
@@ -173,7 +173,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
{
{
internal
int
ulVersion
;
internal
int
ulVersion
;
internal
int
cBuffers
;
internal
int
cBuffers
;
internal
IntPtr
pBuffers
;
//Point to SecBuffer
internal
IntPtr
pBuffers
;
//
Point to SecBuffer
internal
SecurityBufferDesciption
(
int
bufferSize
)
internal
SecurityBufferDesciption
(
int
bufferSize
)
{
{
...
@@ -206,12 +206,12 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
...
@@ -206,12 +206,12 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
{
{
for
(
int
index
=
0
;
index
<
cBuffers
;
index
++)
for
(
int
index
=
0
;
index
<
cBuffers
;
index
++)
{
{
//The bits were written out the following order:
//
The bits were written out the following order:
//int cbBuffer;
//
int cbBuffer;
//int BufferType;
//
int BufferType;
//pvBuffer;
//
pvBuffer;
//What we need to do here is to grab a hold of the pvBuffer allocate by the individual
//What we need to do here is to grab a hold of the pvBuffer allocate by the individual
//SecBuffer and release it...
//
SecBuffer and release it...
int
currentOffset
=
index
*
Marshal
.
SizeOf
(
typeof
(
Buffer
));
int
currentOffset
=
index
*
Marshal
.
SizeOf
(
typeof
(
Buffer
));
var
secBufferpvBuffer
=
Marshal
.
ReadIntPtr
(
pBuffers
,
var
secBufferpvBuffer
=
Marshal
.
ReadIntPtr
(
pBuffers
,
currentOffset
+
Marshal
.
SizeOf
(
typeof
(
int
))
+
Marshal
.
SizeOf
(
typeof
(
int
)));
currentOffset
+
Marshal
.
SizeOf
(
typeof
(
int
))
+
Marshal
.
SizeOf
(
typeof
(
int
)));
...
@@ -249,11 +249,11 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
...
@@ -249,11 +249,11 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
for
(
int
index
=
0
;
index
<
cBuffers
;
index
++)
for
(
int
index
=
0
;
index
<
cBuffers
;
index
++)
{
{
//The bits were written out the following order:
//
The bits were written out the following order:
//int cbBuffer;
//
int cbBuffer;
//int BufferType;
//
int BufferType;
//pvBuffer;
//
pvBuffer;
//What we need to do here calculate the total number of bytes we need to copy...
//
What we need to do here calculate the total number of bytes we need to copy...
int
currentOffset
=
index
*
Marshal
.
SizeOf
(
typeof
(
Buffer
));
int
currentOffset
=
index
*
Marshal
.
SizeOf
(
typeof
(
Buffer
));
bytesToAllocate
+=
Marshal
.
ReadInt32
(
pBuffers
,
currentOffset
);
bytesToAllocate
+=
Marshal
.
ReadInt32
(
pBuffers
,
currentOffset
);
}
}
...
@@ -262,12 +262,12 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
...
@@ -262,12 +262,12 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
for
(
int
index
=
0
,
bufferIndex
=
0
;
index
<
cBuffers
;
index
++)
for
(
int
index
=
0
,
bufferIndex
=
0
;
index
<
cBuffers
;
index
++)
{
{
//The bits were written out the following order:
//
The bits were written out the following order:
//int cbBuffer;
//
int cbBuffer;
//int BufferType;
//
int BufferType;
//pvBuffer;
//
pvBuffer;
//Now iterate over the individual buffers and put them together into a
//
Now iterate over the individual buffers and put them together into a
//byte array...
//
byte array...
int
currentOffset
=
index
*
Marshal
.
SizeOf
(
typeof
(
Buffer
));
int
currentOffset
=
index
*
Marshal
.
SizeOf
(
typeof
(
Buffer
));
int
bytesToCopy
=
Marshal
.
ReadInt32
(
pBuffers
,
currentOffset
);
int
bytesToCopy
=
Marshal
.
ReadInt32
(
pBuffers
,
currentOffset
);
var
secBufferpvBuffer
=
Marshal
.
ReadIntPtr
(
pBuffers
,
var
secBufferpvBuffer
=
Marshal
.
ReadIntPtr
(
pBuffers
,
...
...
Titanium.Web.Proxy/Network/WinAuth/Security/Message.cs
View file @
a8497ab2
...
@@ -69,25 +69,25 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
...
@@ -69,25 +69,25 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
if
(
message
==
null
)
if
(
message
==
null
)
{
{
throw
new
ArgumentNullException
(
"message"
);
throw
new
ArgumentNullException
(
nameof
(
message
)
);
}
}
if
(
message
.
Length
<
12
)
if
(
message
.
Length
<
12
)
{
{
string
msg
=
"Minimum Type3 message length is 12 bytes."
;
string
msg
=
"Minimum Type3 message length is 12 bytes."
;
throw
new
ArgumentOutOfRangeException
(
"message"
,
message
.
Length
,
msg
);
throw
new
ArgumentOutOfRangeException
(
nameof
(
message
)
,
message
.
Length
,
msg
);
}
}
if
(!
CheckHeader
(
message
))
if
(!
CheckHeader
(
message
))
{
{
string
msg
=
"Invalid Type3 message header."
;
string
msg
=
"Invalid Type3 message header."
;
throw
new
ArgumentException
(
msg
,
"message"
);
throw
new
ArgumentException
(
msg
,
nameof
(
message
)
);
}
}
if
(
LittleEndian
.
ToUInt16
(
message
,
56
)
!=
message
.
Length
)
if
(
LittleEndian
.
ToUInt16
(
message
,
56
)
!=
message
.
Length
)
{
{
string
msg
=
"Invalid Type3 message length."
;
string
msg
=
"Invalid Type3 message length."
;
throw
new
ArgumentException
(
msg
,
"message"
);
throw
new
ArgumentException
(
msg
,
nameof
(
message
)
);
}
}
if
(
message
.
Length
>=
64
)
if
(
message
.
Length
>=
64
)
...
...
Titanium.Web.Proxy/Network/WinAuth/Security/WinAuthEndPoint.cs
View file @
a8497ab2
...
@@ -31,7 +31,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
...
@@ -31,7 +31,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
{
{
byte
[]
token
;
byte
[]
token
;
//null for initial call
//
null for initial call
var
serverToken
=
new
SecurityBufferDesciption
();
var
serverToken
=
new
SecurityBufferDesciption
();
var
clientToken
=
new
SecurityBufferDesciption
(
MaximumTokenSize
);
var
clientToken
=
new
SecurityBufferDesciption
(
MaximumTokenSize
);
...
@@ -99,7 +99,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
...
@@ -99,7 +99,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
{
{
byte
[]
token
;
byte
[]
token
;
//user server challenge
//
user server challenge
var
serverToken
=
new
SecurityBufferDesciption
(
serverChallenge
);
var
serverToken
=
new
SecurityBufferDesciption
(
serverChallenge
);
var
clientToken
=
new
SecurityBufferDesciption
(
MaximumTokenSize
);
var
clientToken
=
new
SecurityBufferDesciption
(
MaximumTokenSize
);
...
@@ -156,7 +156,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
...
@@ -156,7 +156,7 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
authStates
.
Remove
(
cache
.
Key
);
authStates
.
Remove
(
cache
.
Key
);
}
}
//after a minute come back to check for outdated certificates in cache
//
after a minute come back to check for outdated certificates in cache
await
Task
.
Delay
(
1000
*
60
);
await
Task
.
Delay
(
1000
*
60
);
}
}
...
@@ -206,44 +206,44 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
...
@@ -206,44 +206,44 @@ namespace Titanium.Web.Proxy.Network.WinAuth.Security
#
region
Native
calls
to
secur32
.
dll
#
region
Native
calls
to
secur32
.
dll
[
DllImport
(
"secur32.dll"
,
SetLastError
=
true
)]
[
DllImport
(
"secur32.dll"
,
SetLastError
=
true
)]
private
static
extern
int
InitializeSecurityContext
(
ref
SecurityHandle
phCredential
,
//PCredHandle
private
static
extern
int
InitializeSecurityContext
(
ref
SecurityHandle
phCredential
,
//
PCredHandle
IntPtr
phContext
,
//PCtxtHandle
IntPtr
phContext
,
//
PCtxtHandle
string
pszTargetName
,
string
pszTargetName
,
int
fContextReq
,
int
fContextReq
,
int
reserved1
,
int
reserved1
,
int
targetDataRep
,
int
targetDataRep
,
ref
SecurityBufferDesciption
pInput
,
//PSecBufferDesc SecBufferDesc
ref
SecurityBufferDesciption
pInput
,
//
PSecBufferDesc SecBufferDesc
int
reserved2
,
int
reserved2
,
out
SecurityHandle
phNewContext
,
//PCtxtHandle
out
SecurityHandle
phNewContext
,
//
PCtxtHandle
out
SecurityBufferDesciption
pOutput
,
//PSecBufferDesc SecBufferDesc
out
SecurityBufferDesciption
pOutput
,
//
PSecBufferDesc SecBufferDesc
out
uint
pfContextAttr
,
//managed ulong == 64 bits!!!
out
uint
pfContextAttr
,
//
managed ulong == 64 bits!!!
out
SecurityInteger
ptsExpiry
);
//PTimeStamp
out
SecurityInteger
ptsExpiry
);
//
PTimeStamp
[
DllImport
(
"secur32"
,
CharSet
=
CharSet
.
Auto
,
SetLastError
=
true
)]
[
DllImport
(
"secur32"
,
CharSet
=
CharSet
.
Auto
,
SetLastError
=
true
)]
private
static
extern
int
InitializeSecurityContext
(
ref
SecurityHandle
phCredential
,
//PCredHandle
private
static
extern
int
InitializeSecurityContext
(
ref
SecurityHandle
phCredential
,
//
PCredHandle
ref
SecurityHandle
phContext
,
//PCtxtHandle
ref
SecurityHandle
phContext
,
//
PCtxtHandle
string
pszTargetName
,
string
pszTargetName
,
int
fContextReq
,
int
fContextReq
,
int
reserved1
,
int
reserved1
,
int
targetDataRep
,
int
targetDataRep
,
ref
SecurityBufferDesciption
secBufferDesc
,
//PSecBufferDesc SecBufferDesc
ref
SecurityBufferDesciption
secBufferDesc
,
//
PSecBufferDesc SecBufferDesc
int
reserved2
,
int
reserved2
,
out
SecurityHandle
phNewContext
,
//PCtxtHandle
out
SecurityHandle
phNewContext
,
//
PCtxtHandle
out
SecurityBufferDesciption
pOutput
,
//PSecBufferDesc SecBufferDesc
out
SecurityBufferDesciption
pOutput
,
//
PSecBufferDesc SecBufferDesc
out
uint
pfContextAttr
,
//managed ulong == 64 bits!!!
out
uint
pfContextAttr
,
//
managed ulong == 64 bits!!!
out
SecurityInteger
ptsExpiry
);
//PTimeStamp
out
SecurityInteger
ptsExpiry
);
//
PTimeStamp
[
DllImport
(
"secur32.dll"
,
CharSet
=
CharSet
.
Auto
,
SetLastError
=
false
)]
[
DllImport
(
"secur32.dll"
,
CharSet
=
CharSet
.
Auto
,
SetLastError
=
false
)]
private
static
extern
int
AcquireCredentialsHandle
(
private
static
extern
int
AcquireCredentialsHandle
(
string
pszPrincipal
,
//SEC_CHAR*
string
pszPrincipal
,
//
SEC_CHAR*
string
pszPackage
,
//
SEC_CHAR* //
"Kerberos","NTLM","Negotiative"
string
pszPackage
,
//
SEC_CHAR* //
"Kerberos","NTLM","Negotiative"
int
fCredentialUse
,
int
fCredentialUse
,
IntPtr
pAuthenticationId
,
//
_LUID AuthenticationID,//pvLogonID, //
PLUID
IntPtr
pAuthenticationId
,
//
_LUID AuthenticationID,//pvLogonID, //
PLUID
IntPtr
pAuthData
,
//PVOID
IntPtr
pAuthData
,
//
PVOID
int
pGetKeyFn
,
//SEC_GET_KEY_FN
int
pGetKeyFn
,
//
SEC_GET_KEY_FN
IntPtr
pvGetKeyArgument
,
//PVOID
IntPtr
pvGetKeyArgument
,
//
PVOID
ref
SecurityHandle
phCredential
,
//
SecHandle //
PCtxtHandle ref
ref
SecurityHandle
phCredential
,
//
SecHandle //
PCtxtHandle ref
ref
SecurityInteger
ptsExpiry
);
//
PTimeStamp //
TimeStamp ref
ref
SecurityInteger
ptsExpiry
);
//
PTimeStamp //
TimeStamp ref
#
endregion
#
endregion
}
}
...
...
Titanium.Web.Proxy/ProxyAuthorizationHandler.cs
View file @
a8497ab2
...
@@ -20,7 +20,7 @@ namespace Titanium.Web.Proxy
...
@@ -20,7 +20,7 @@ namespace Titanium.Web.Proxy
/// <returns>True if authorized.</returns>
/// <returns>True if authorized.</returns>
private
async
Task
<
bool
>
CheckAuthorization
(
SessionEventArgsBase
session
)
private
async
Task
<
bool
>
CheckAuthorization
(
SessionEventArgsBase
session
)
{
{
//If we are not authorizing clients return true
//
If we are not authorizing clients return true
if
(
AuthenticateUserFunc
==
null
)
if
(
AuthenticateUserFunc
==
null
)
{
{
return
true
;
return
true
;
...
@@ -41,7 +41,7 @@ namespace Titanium.Web.Proxy
...
@@ -41,7 +41,7 @@ namespace Titanium.Web.Proxy
if
(
headerValueParts
.
Length
!=
2
||
if
(
headerValueParts
.
Length
!=
2
||
!
headerValueParts
[
0
].
EqualsIgnoreCase
(
KnownHeaders
.
ProxyAuthorizationBasic
))
!
headerValueParts
[
0
].
EqualsIgnoreCase
(
KnownHeaders
.
ProxyAuthorizationBasic
))
{
{
//Return not authorized
//
Return not authorized
session
.
WebSession
.
Response
=
CreateAuthentication407Response
(
"Proxy Authentication Invalid"
);
session
.
WebSession
.
Response
=
CreateAuthentication407Response
(
"Proxy Authentication Invalid"
);
return
false
;
return
false
;
}
}
...
@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy
...
@@ -50,7 +50,7 @@ namespace Titanium.Web.Proxy
int
colonIndex
=
decoded
.
IndexOf
(
':'
);
int
colonIndex
=
decoded
.
IndexOf
(
':'
);
if
(
colonIndex
==
-
1
)
if
(
colonIndex
==
-
1
)
{
{
//Return not authorized
//
Return not authorized
session
.
WebSession
.
Response
=
CreateAuthentication407Response
(
"Proxy Authentication Invalid"
);
session
.
WebSession
.
Response
=
CreateAuthentication407Response
(
"Proxy Authentication Invalid"
);
return
false
;
return
false
;
}
}
...
@@ -70,7 +70,7 @@ namespace Titanium.Web.Proxy
...
@@ -70,7 +70,7 @@ namespace Titanium.Web.Proxy
ExceptionFunc
(
new
ProxyAuthorizationException
(
"Error whilst authorizing request"
,
session
,
e
,
ExceptionFunc
(
new
ProxyAuthorizationException
(
"Error whilst authorizing request"
,
session
,
e
,
httpHeaders
));
httpHeaders
));
//Return not authorized
//
Return not authorized
session
.
WebSession
.
Response
=
CreateAuthentication407Response
(
"Proxy Authentication Invalid"
);
session
.
WebSession
.
Response
=
CreateAuthentication407Response
(
"Proxy Authentication Invalid"
);
return
false
;
return
false
;
}
}
...
...
Titanium.Web.Proxy/ProxyServer.cs
View file @
a8497ab2
...
@@ -92,7 +92,7 @@ namespace Titanium.Web.Proxy
...
@@ -92,7 +92,7 @@ namespace Titanium.Web.Proxy
bool
userTrustRootCertificate
=
true
,
bool
machineTrustRootCertificate
=
false
,
bool
userTrustRootCertificate
=
true
,
bool
machineTrustRootCertificate
=
false
,
bool
trustRootCertificateAsAdmin
=
false
)
bool
trustRootCertificateAsAdmin
=
false
)
{
{
//default values
//
default values
ConnectionTimeOutSeconds
=
60
;
ConnectionTimeOutSeconds
=
60
;
ProxyEndPoints
=
new
List
<
ProxyEndPoint
>();
ProxyEndPoints
=
new
List
<
ProxyEndPoint
>();
...
@@ -357,7 +357,7 @@ namespace Titanium.Web.Proxy
...
@@ -357,7 +357,7 @@ namespace Titanium.Web.Proxy
{
{
CertificateManager
.
EnsureRootCertificate
();
CertificateManager
.
EnsureRootCertificate
();
//If certificate was trusted by the machine
//
If certificate was trusted by the machine
if
(!
CertificateManager
.
CertValidated
)
if
(!
CertificateManager
.
CertValidated
)
{
{
protocolType
=
protocolType
&
~
ProxyProtocolType
.
Https
;
protocolType
=
protocolType
&
~
ProxyProtocolType
.
Https
;
...
@@ -365,7 +365,7 @@ namespace Titanium.Web.Proxy
...
@@ -365,7 +365,7 @@ namespace Titanium.Web.Proxy
}
}
}
}
//clear any settings previously added
//
clear any settings previously added
if
(
isHttp
)
if
(
isHttp
)
{
{
ProxyEndPoints
.
OfType
<
ExplicitProxyEndPoint
>().
ToList
().
ForEach
(
x
=>
x
.
IsSystemHttpProxy
=
false
);
ProxyEndPoints
.
OfType
<
ExplicitProxyEndPoint
>().
ToList
().
ForEach
(
x
=>
x
.
IsSystemHttpProxy
=
false
);
...
@@ -472,8 +472,8 @@ namespace Titanium.Web.Proxy
...
@@ -472,8 +472,8 @@ namespace Titanium.Web.Proxy
CertificateManager
.
EnsureRootCertificate
();
CertificateManager
.
EnsureRootCertificate
();
}
}
//clear any system proxy settings which is pointing to our own endpoint (causing a cycle)
//
clear any system proxy settings which is pointing to our own endpoint (causing a cycle)
//due to non gracious proxy shutdown before or something else
//
due to non gracious proxy shutdown before or something else
if
(
systemProxySettingsManager
!=
null
&&
RunTime
.
IsWindows
)
if
(
systemProxySettingsManager
!=
null
&&
RunTime
.
IsWindows
)
{
{
var
proxyInfo
=
systemProxySettingsManager
.
GetProxyInfoFromRegistry
();
var
proxyInfo
=
systemProxySettingsManager
.
GetProxyInfoFromRegistry
();
...
@@ -622,7 +622,7 @@ namespace Titanium.Web.Proxy
...
@@ -622,7 +622,7 @@ namespace Titanium.Web.Proxy
try
try
{
{
//based on end point type call appropriate request handlers
//
based on end point type call appropriate request handlers
tcpClient
=
endPoint
.
Listener
.
EndAcceptTcpClient
(
asyn
);
tcpClient
=
endPoint
.
Listener
.
EndAcceptTcpClient
(
asyn
);
}
}
catch
(
ObjectDisposedException
)
catch
(
ObjectDisposedException
)
...
@@ -634,7 +634,7 @@ namespace Titanium.Web.Proxy
...
@@ -634,7 +634,7 @@ namespace Titanium.Web.Proxy
}
}
catch
catch
{
{
//Other errors are discarded to keep proxy running
//
Other errors are discarded to keep proxy running
}
}
if
(
tcpClient
!=
null
)
if
(
tcpClient
!=
null
)
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
a8497ab2
...
@@ -51,8 +51,8 @@ namespace Titanium.Web.Proxy
...
@@ -51,8 +51,8 @@ namespace Titanium.Web.Proxy
try
try
{
{
//Loop through each subsequest request on this particular client connection
//
Loop through each subsequest request on this particular client connection
//(assuming HTTP connection is kept alive by client)
//
(assuming HTTP connection is kept alive by client)
while
(
true
)
while
(
true
)
{
{
// read the request line
// read the request line
...
@@ -76,7 +76,7 @@ namespace Titanium.Web.Proxy
...
@@ -76,7 +76,7 @@ namespace Titanium.Web.Proxy
Request
.
ParseRequestLine
(
httpCmd
,
out
string
httpMethod
,
out
string
httpUrl
,
Request
.
ParseRequestLine
(
httpCmd
,
out
string
httpMethod
,
out
string
httpUrl
,
out
var
version
);
out
var
version
);
//Read the request headers in to unique and non-unique header collections
//
Read the request headers in to unique and non-unique header collections
await
HeaderParser
.
ReadHeaders
(
clientStream
,
args
.
WebSession
.
Request
.
Headers
,
await
HeaderParser
.
ReadHeaders
(
clientStream
,
args
.
WebSession
.
Request
.
Headers
,
cancellationToken
);
cancellationToken
);
...
@@ -124,12 +124,12 @@ namespace Titanium.Web.Proxy
...
@@ -124,12 +124,12 @@ namespace Titanium.Web.Proxy
if
(!
args
.
IsTransparent
)
if
(!
args
.
IsTransparent
)
{
{
//proxy authorization check
//
proxy authorization check
if
(
httpsConnectHostname
==
null
&&
await
CheckAuthorization
(
args
)
==
false
)
if
(
httpsConnectHostname
==
null
&&
await
CheckAuthorization
(
args
)
==
false
)
{
{
await
InvokeBeforeResponse
(
args
);
await
InvokeBeforeResponse
(
args
);
//send the response
//
send the response
await
clientStreamWriter
.
WriteResponseAsync
(
args
.
WebSession
.
Response
,
await
clientStreamWriter
.
WriteResponseAsync
(
args
.
WebSession
.
Response
,
cancellationToken
:
cancellationToken
);
cancellationToken
:
cancellationToken
);
return
;
return
;
...
@@ -139,9 +139,9 @@ namespace Titanium.Web.Proxy
...
@@ -139,9 +139,9 @@ namespace Titanium.Web.Proxy
request
.
Host
=
request
.
RequestUri
.
Authority
;
request
.
Host
=
request
.
RequestUri
.
Authority
;
}
}
//if win auth is enabled
//
if win auth is enabled
//we need a cache of request body
//
we need a cache of request body
//so that we can send it after authentication in WinAuthHandler.cs
//
so that we can send it after authentication in WinAuthHandler.cs
if
(
isWindowsAuthenticationEnabledAndSupported
&&
request
.
HasBody
)
if
(
isWindowsAuthenticationEnabledAndSupported
&&
request
.
HasBody
)
{
{
await
args
.
GetRequestBody
(
cancellationToken
);
await
args
.
GetRequestBody
(
cancellationToken
);
...
@@ -149,14 +149,14 @@ namespace Titanium.Web.Proxy
...
@@ -149,14 +149,14 @@ namespace Titanium.Web.Proxy
request
.
OriginalHasBody
=
request
.
HasBody
;
request
.
OriginalHasBody
=
request
.
HasBody
;
//If user requested interception do it
//
If user requested interception do it
await
InvokeBeforeRequest
(
args
);
await
InvokeBeforeRequest
(
args
);
var
response
=
args
.
WebSession
.
Response
;
var
response
=
args
.
WebSession
.
Response
;
if
(
request
.
CancelRequest
)
if
(
request
.
CancelRequest
)
{
{
//syphon out the request body from client before setting the new body
//
syphon out the request body from client before setting the new body
await
args
.
SyphonOutBodyAsync
(
true
,
cancellationToken
);
await
args
.
SyphonOutBodyAsync
(
true
,
cancellationToken
);
await
HandleHttpSessionResponse
(
args
);
await
HandleHttpSessionResponse
(
args
);
...
@@ -169,7 +169,7 @@ namespace Titanium.Web.Proxy
...
@@ -169,7 +169,7 @@ namespace Titanium.Web.Proxy
continue
;
continue
;
}
}
//create a new connection if hostname/upstream end point changes
//
create a new connection if hostname/upstream end point changes
if
(
serverConnection
!=
null
if
(
serverConnection
!=
null
&&
(!
serverConnection
.
HostName
.
Equals
(
request
.
RequestUri
.
Host
,
&&
(!
serverConnection
.
HostName
.
Equals
(
request
.
RequestUri
.
Host
,
StringComparison
.
OrdinalIgnoreCase
)
StringComparison
.
OrdinalIgnoreCase
)
...
@@ -185,10 +185,10 @@ namespace Titanium.Web.Proxy
...
@@ -185,10 +185,10 @@ namespace Titanium.Web.Proxy
serverConnection
=
await
GetServerConnection
(
args
,
false
,
cancellationToken
);
serverConnection
=
await
GetServerConnection
(
args
,
false
,
cancellationToken
);
}
}
//if upgrading to websocket then relay the requet without reading the contents
//
if upgrading to websocket then relay the requet without reading the contents
if
(
request
.
UpgradeToWebSocket
)
if
(
request
.
UpgradeToWebSocket
)
{
{
//prepare the prefix content
//
prepare the prefix content
await
serverConnection
.
StreamWriter
.
WriteLineAsync
(
httpCmd
,
cancellationToken
);
await
serverConnection
.
StreamWriter
.
WriteLineAsync
(
httpCmd
,
cancellationToken
);
await
serverConnection
.
StreamWriter
.
WriteHeadersAsync
(
request
.
Headers
,
await
serverConnection
.
StreamWriter
.
WriteHeadersAsync
(
request
.
Headers
,
cancellationToken
:
cancellationToken
);
cancellationToken
:
cancellationToken
);
...
@@ -210,7 +210,7 @@ namespace Titanium.Web.Proxy
...
@@ -210,7 +210,7 @@ namespace Titanium.Web.Proxy
cancellationToken
:
cancellationToken
);
cancellationToken
:
cancellationToken
);
}
}
//If user requested call back then do it
//
If user requested call back then do it
if
(!
args
.
WebSession
.
Response
.
Locked
)
if
(!
args
.
WebSession
.
Response
.
Locked
)
{
{
await
InvokeBeforeResponse
(
args
);
await
InvokeBeforeResponse
(
args
);
...
@@ -224,7 +224,7 @@ namespace Titanium.Web.Proxy
...
@@ -224,7 +224,7 @@ namespace Titanium.Web.Proxy
return
;
return
;
}
}
//construct the web request that we are going to issue on behalf of the client.
//
construct the web request that we are going to issue on behalf of the client.
await
HandleHttpSessionRequestInternal
(
serverConnection
,
args
);
await
HandleHttpSessionRequestInternal
(
serverConnection
,
args
);
if
(
args
.
WebSession
.
ServerConnection
==
null
)
if
(
args
.
WebSession
.
ServerConnection
==
null
)
...
@@ -232,7 +232,7 @@ namespace Titanium.Web.Proxy
...
@@ -232,7 +232,7 @@ namespace Titanium.Web.Proxy
return
;
return
;
}
}
//if connection is closing exit
//
if connection is closing exit
if
(!
response
.
KeepAlive
)
if
(!
response
.
KeepAlive
)
{
{
return
;
return
;
...
@@ -282,8 +282,8 @@ namespace Titanium.Web.Proxy
...
@@ -282,8 +282,8 @@ namespace Titanium.Web.Proxy
var
body
=
request
.
CompressBodyAndUpdateContentLength
();
var
body
=
request
.
CompressBodyAndUpdateContentLength
();
//if expect continue is enabled then send the headers first
//
if expect continue is enabled then send the headers first
//and see if server would return 100 conitinue
//
and see if server would return 100 conitinue
if
(
request
.
ExpectContinue
)
if
(
request
.
ExpectContinue
)
{
{
args
.
WebSession
.
SetConnection
(
serverConnection
);
args
.
WebSession
.
SetConnection
(
serverConnection
);
...
@@ -291,7 +291,7 @@ namespace Titanium.Web.Proxy
...
@@ -291,7 +291,7 @@ namespace Titanium.Web.Proxy
cancellationToken
);
cancellationToken
);
}
}
//If 100 continue was the response inform that to the client
//
If 100 continue was the response inform that to the client
if
(
Enable100ContinueBehaviour
)
if
(
Enable100ContinueBehaviour
)
{
{
var
clientStreamWriter
=
args
.
ProxyClient
.
ClientStreamWriter
;
var
clientStreamWriter
=
args
.
ProxyClient
.
ClientStreamWriter
;
...
@@ -310,7 +310,7 @@ namespace Titanium.Web.Proxy
...
@@ -310,7 +310,7 @@ namespace Titanium.Web.Proxy
}
}
}
}
//If expect continue is not enabled then set the connectio and send request headers
//
If expect continue is not enabled then set the connectio and send request headers
if
(!
request
.
ExpectContinue
)
if
(!
request
.
ExpectContinue
)
{
{
args
.
WebSession
.
SetConnection
(
serverConnection
);
args
.
WebSession
.
SetConnection
(
serverConnection
);
...
@@ -318,7 +318,7 @@ namespace Titanium.Web.Proxy
...
@@ -318,7 +318,7 @@ namespace Titanium.Web.Proxy
cancellationToken
);
cancellationToken
);
}
}
//check if content-length is > 0
//
check if content-length is > 0
if
(
request
.
ContentLength
>
0
)
if
(
request
.
ContentLength
>
0
)
{
{
if
(
request
.
IsBodyRead
)
if
(
request
.
IsBodyRead
)
...
@@ -339,7 +339,7 @@ namespace Titanium.Web.Proxy
...
@@ -339,7 +339,7 @@ namespace Titanium.Web.Proxy
}
}
}
}
//If not expectation failed response was returned by server then parse response
//
If not expectation failed response was returned by server then parse response
if
(!
request
.
ExpectationFailed
)
if
(!
request
.
ExpectationFailed
)
{
{
await
HandleHttpSessionResponse
(
args
);
await
HandleHttpSessionResponse
(
args
);
...
...
Titanium.Web.Proxy/ResponseHandler.cs
View file @
a8497ab2
...
@@ -23,13 +23,13 @@ namespace Titanium.Web.Proxy
...
@@ -23,13 +23,13 @@ namespace Titanium.Web.Proxy
try
try
{
{
var
cancellationToken
=
args
.
CancellationTokenSource
.
Token
;
var
cancellationToken
=
args
.
CancellationTokenSource
.
Token
;
//read response & headers from server
//
read response & headers from server
await
args
.
WebSession
.
ReceiveResponse
(
cancellationToken
);
await
args
.
WebSession
.
ReceiveResponse
(
cancellationToken
);
var
response
=
args
.
WebSession
.
Response
;
var
response
=
args
.
WebSession
.
Response
;
args
.
ReRequest
=
false
;
args
.
ReRequest
=
false
;
//check for windows authentication
//
check for windows authentication
if
(
isWindowsAuthenticationEnabledAndSupported
)
if
(
isWindowsAuthenticationEnabledAndSupported
)
{
{
if
(
response
.
StatusCode
==
(
int
)
HttpStatusCode
.
Unauthorized
)
if
(
response
.
StatusCode
==
(
int
)
HttpStatusCode
.
Unauthorized
)
...
@@ -44,7 +44,7 @@ namespace Titanium.Web.Proxy
...
@@ -44,7 +44,7 @@ namespace Titanium.Web.Proxy
response
.
OriginalHasBody
=
response
.
HasBody
;
response
.
OriginalHasBody
=
response
.
HasBody
;
//if user requested call back then do it
//
if user requested call back then do it
if
(!
response
.
Locked
)
if
(!
response
.
Locked
)
{
{
await
InvokeBeforeResponse
(
args
);
await
InvokeBeforeResponse
(
args
);
...
@@ -61,7 +61,7 @@ namespace Titanium.Web.Proxy
...
@@ -61,7 +61,7 @@ namespace Titanium.Web.Proxy
if
(!
response
.
TerminateResponse
)
if
(!
response
.
TerminateResponse
)
{
{
//syphon out the response body from server before setting the new body
//
syphon out the response body from server before setting the new body
await
args
.
SyphonOutBodyAsync
(
false
,
cancellationToken
);
await
args
.
SyphonOutBodyAsync
(
false
,
cancellationToken
);
}
}
else
else
...
@@ -73,11 +73,11 @@ namespace Titanium.Web.Proxy
...
@@ -73,11 +73,11 @@ namespace Titanium.Web.Proxy
return
;
return
;
}
}
//if user requested to send request again
//
if user requested to send request again
//likely after making modifications from User Response Handler
//
likely after making modifications from User Response Handler
if
(
args
.
ReRequest
)
if
(
args
.
ReRequest
)
{
{
//clear current response
//
clear current response
await
args
.
ClearResponse
(
cancellationToken
);
await
args
.
ClearResponse
(
cancellationToken
);
await
HandleHttpSessionRequestInternal
(
args
.
WebSession
.
ServerConnection
,
args
);
await
HandleHttpSessionRequestInternal
(
args
.
WebSession
.
ServerConnection
,
args
);
return
;
return
;
...
@@ -85,7 +85,7 @@ namespace Titanium.Web.Proxy
...
@@ -85,7 +85,7 @@ namespace Titanium.Web.Proxy
response
.
Locked
=
true
;
response
.
Locked
=
true
;
//Write back to client 100-conitinue response if that's what server returned
//
Write back to client 100-conitinue response if that's what server returned
if
(
response
.
Is100Continue
)
if
(
response
.
Is100Continue
)
{
{
await
clientStreamWriter
.
WriteResponseStatusAsync
(
response
.
HttpVersion
,
await
clientStreamWriter
.
WriteResponseStatusAsync
(
response
.
HttpVersion
,
...
@@ -110,12 +110,12 @@ namespace Titanium.Web.Proxy
...
@@ -110,12 +110,12 @@ namespace Titanium.Web.Proxy
}
}
else
else
{
{
//Write back response status to client
//
Write back response status to client
await
clientStreamWriter
.
WriteResponseStatusAsync
(
response
.
HttpVersion
,
response
.
StatusCode
,
await
clientStreamWriter
.
WriteResponseStatusAsync
(
response
.
HttpVersion
,
response
.
StatusCode
,
response
.
StatusDescription
,
cancellationToken
);
response
.
StatusDescription
,
cancellationToken
);
await
clientStreamWriter
.
WriteHeadersAsync
(
response
.
Headers
,
cancellationToken
:
cancellationToken
);
await
clientStreamWriter
.
WriteHeadersAsync
(
response
.
Headers
,
cancellationToken
:
cancellationToken
);
//Write body if exists
//
Write body if exists
if
(
response
.
HasBody
)
if
(
response
.
HasBody
)
{
{
await
args
.
CopyResponseBodyAsync
(
clientStreamWriter
,
TransformationMode
.
None
,
await
args
.
CopyResponseBodyAsync
(
clientStreamWriter
,
TransformationMode
.
None
,
...
...
Titanium.Web.Proxy/TransparentClientHandler.cs
View file @
a8497ab2
...
@@ -69,10 +69,10 @@ namespace Titanium.Web.Proxy
...
@@ -69,10 +69,10 @@ namespace Titanium.Web.Proxy
string
certName
=
HttpHelper
.
GetWildCardDomainName
(
httpsHostName
);
string
certName
=
HttpHelper
.
GetWildCardDomainName
(
httpsHostName
);
var
certificate
=
await
CertificateManager
.
CreateCertificateAsync
(
certName
);
var
certificate
=
await
CertificateManager
.
CreateCertificateAsync
(
certName
);
//Successfully managed to authenticate the client using the fake certificate
//
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
//
HTTPS server created - we can now decrypt the client's traffic
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStream
=
new
CustomBufferedStream
(
sslStream
,
BufferSize
);
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
clientStreamWriter
=
new
HttpResponseWriter
(
clientStream
,
BufferSize
);
...
@@ -86,7 +86,7 @@ namespace Titanium.Web.Proxy
...
@@ -86,7 +86,7 @@ namespace Titanium.Web.Proxy
}
}
else
else
{
{
//create new connection
//
create new connection
var
connection
=
new
TcpClient
(
UpStreamEndPoint
);
var
connection
=
new
TcpClient
(
UpStreamEndPoint
);
await
connection
.
ConnectAsync
(
httpsHostName
,
endPoint
.
Port
);
await
connection
.
ConnectAsync
(
httpsHostName
,
endPoint
.
Port
);
connection
.
ReceiveTimeout
=
ConnectionTimeOutSeconds
*
1000
;
connection
.
ReceiveTimeout
=
ConnectionTimeOutSeconds
*
1000
;
...
@@ -123,8 +123,8 @@ namespace Titanium.Web.Proxy
...
@@ -123,8 +123,8 @@ namespace Titanium.Web.Proxy
}
}
}
}
//HTTPS server created - we can now decrypt the client's traffic
//
HTTPS server created - we can now decrypt the client's traffic
//Now create the request
//
Now create the request
await
HandleHttpSessionRequest
(
endPoint
,
clientConnection
,
clientStream
,
clientStreamWriter
,
await
HandleHttpSessionRequest
(
endPoint
,
clientConnection
,
clientStream
,
clientStreamWriter
,
cancellationTokenSource
,
isHttps
?
httpsHostName
:
null
,
null
);
cancellationTokenSource
,
isHttps
?
httpsHostName
:
null
,
null
);
}
}
...
...
Titanium.Web.Proxy/WinAuthHandler.cs
View file @
a8497ab2
...
@@ -19,7 +19,8 @@ namespace Titanium.Web.Proxy
...
@@ -19,7 +19,8 @@ namespace Titanium.Web.Proxy
private
static
readonly
HashSet
<
string
>
authHeaderNames
=
new
HashSet
<
string
>(
StringComparer
.
OrdinalIgnoreCase
)
private
static
readonly
HashSet
<
string
>
authHeaderNames
=
new
HashSet
<
string
>(
StringComparer
.
OrdinalIgnoreCase
)
{
{
"WWW-Authenticate"
,
"WWW-Authenticate"
,
//IIS 6.0 messed up names below
// IIS 6.0 messed up names below
"WWWAuthenticate"
,
"WWWAuthenticate"
,
"NTLMAuthorization"
,
"NTLMAuthorization"
,
"NegotiateAuthorization"
,
"NegotiateAuthorization"
,
...
@@ -51,7 +52,7 @@ namespace Titanium.Web.Proxy
...
@@ -51,7 +52,7 @@ namespace Titanium.Web.Proxy
var
response
=
args
.
WebSession
.
Response
;
var
response
=
args
.
WebSession
.
Response
;
//check in non-unique headers first
//
check in non-unique headers first
var
header
=
response
.
Headers
.
NonUniqueHeaders
.
FirstOrDefault
(
x
=>
authHeaderNames
.
Contains
(
x
.
Key
));
var
header
=
response
.
Headers
.
NonUniqueHeaders
.
FirstOrDefault
(
x
=>
authHeaderNames
.
Contains
(
x
.
Key
));
if
(!
header
.
Equals
(
new
KeyValuePair
<
string
,
List
<
HttpHeader
>>()))
if
(!
header
.
Equals
(
new
KeyValuePair
<
string
,
List
<
HttpHeader
>>()))
...
@@ -66,12 +67,12 @@ namespace Titanium.Web.Proxy
...
@@ -66,12 +67,12 @@ namespace Titanium.Web.Proxy
x
=>
authSchemes
.
Any
(
y
=>
x
.
Value
.
StartsWith
(
y
,
StringComparison
.
OrdinalIgnoreCase
)));
x
=>
authSchemes
.
Any
(
y
=>
x
.
Value
.
StartsWith
(
y
,
StringComparison
.
OrdinalIgnoreCase
)));
}
}
//check in unique headers
//
check in unique headers
if
(
authHeader
==
null
)
if
(
authHeader
==
null
)
{
{
headerName
=
null
;
headerName
=
null
;
//check in non-unique headers first
//
check in non-unique headers first
var
uHeader
=
response
.
Headers
.
Headers
.
FirstOrDefault
(
x
=>
authHeaderNames
.
Contains
(
x
.
Key
));
var
uHeader
=
response
.
Headers
.
Headers
.
FirstOrDefault
(
x
=>
authHeaderNames
.
Contains
(
x
.
Key
));
if
(!
uHeader
.
Equals
(
new
KeyValuePair
<
string
,
HttpHeader
>()))
if
(!
uHeader
.
Equals
(
new
KeyValuePair
<
string
,
HttpHeader
>()))
...
@@ -104,26 +105,26 @@ namespace Titanium.Web.Proxy
...
@@ -104,26 +105,26 @@ namespace Titanium.Web.Proxy
var
request
=
args
.
WebSession
.
Request
;
var
request
=
args
.
WebSession
.
Request
;
//clear any existing headers to avoid confusing bad servers
//
clear any existing headers to avoid confusing bad servers
request
.
Headers
.
RemoveHeader
(
KnownHeaders
.
Authorization
);
request
.
Headers
.
RemoveHeader
(
KnownHeaders
.
Authorization
);
//initial value will match exactly any of the schemes
//
initial value will match exactly any of the schemes
if
(
scheme
!=
null
)
if
(
scheme
!=
null
)
{
{
string
clientToken
=
WinAuthHandler
.
GetInitialAuthToken
(
request
.
Host
,
scheme
,
args
.
Id
);
string
clientToken
=
WinAuthHandler
.
GetInitialAuthToken
(
request
.
Host
,
scheme
,
args
.
Id
);
string
auth
=
string
.
Concat
(
scheme
,
clientToken
);
string
auth
=
string
.
Concat
(
scheme
,
clientToken
);
//replace existing authorization header if any
//
replace existing authorization header if any
request
.
Headers
.
SetOrAddHeaderValue
(
KnownHeaders
.
Authorization
,
auth
);
request
.
Headers
.
SetOrAddHeaderValue
(
KnownHeaders
.
Authorization
,
auth
);
//don't need to send body for Authorization request
//
don't need to send body for Authorization request
if
(
request
.
HasBody
)
if
(
request
.
HasBody
)
{
{
request
.
ContentLength
=
0
;
request
.
ContentLength
=
0
;
}
}
}
}
//challenge value will start with any of the scheme selected
//
challenge value will start with any of the scheme selected
else
else
{
{
scheme
=
authSchemes
.
First
(
x
=>
scheme
=
authSchemes
.
First
(
x
=>
...
@@ -135,19 +136,19 @@ namespace Titanium.Web.Proxy
...
@@ -135,19 +136,19 @@ namespace Titanium.Web.Proxy
string
auth
=
string
.
Concat
(
scheme
,
clientToken
);
string
auth
=
string
.
Concat
(
scheme
,
clientToken
);
//there will be an existing header from initial client request
//
there will be an existing header from initial client request
request
.
Headers
.
SetOrAddHeaderValue
(
KnownHeaders
.
Authorization
,
auth
);
request
.
Headers
.
SetOrAddHeaderValue
(
KnownHeaders
.
Authorization
,
auth
);
//send body for final auth request
//
send body for final auth request
if
(
request
.
OriginalHasBody
)
if
(
request
.
OriginalHasBody
)
{
{
request
.
ContentLength
=
request
.
Body
.
Length
;
request
.
ContentLength
=
request
.
Body
.
Length
;
}
}
}
}
//Need to revisit this.
//
Need to revisit this.
//Should we cache all Set-Cokiee headers from server during auth process
//
Should we cache all Set-Cokiee headers from server during auth process
//and send it to client after auth?
//
and send it to client after auth?
// Let ResponseHandler send the updated request
// Let ResponseHandler send the updated request
args
.
ReRequest
=
true
;
args
.
ReRequest
=
true
;
...
...
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