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
4c75ae15
Commit
4c75ae15
authored
Sep 01, 2016
by
ilushka85
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support for authentication functions added
parent
d301c72c
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
133 additions
and
16 deletions
+133
-16
ProxyServer.cs
Titanium.Web.Proxy/ProxyServer.cs
+19
-9
RequestHandler.cs
Titanium.Web.Proxy/RequestHandler.cs
+114
-7
No files found.
Titanium.Web.Proxy/ProxyServer.cs
View file @
4c75ae15
...
...
@@ -18,8 +18,23 @@ namespace Titanium.Web.Proxy
/// </summary>
public
partial
class
ProxyServer
:
IDisposable
{
public
Func
<
ExternalProxy
>
GetCustomUpStreamHttpProxyFunc
=
null
;
public
Func
<
ExternalProxy
>
GetCustomUpStreamHttpsProxyFunc
=
null
;
public
Func
<
string
,
string
,
Task
<
bool
>>
AuthenticateUserFunc
{
get
;
set
;
}
//parameter is list of headers
public
Func
<
IEnumerable
<
HttpHeader
>,
ExternalProxy
>
GetCustomUpStreamHttpProxyFunc
{
get
;
set
;
}
//parameter is list of headers
public
Func
<
IEnumerable
<
HttpHeader
>,
ExternalProxy
>
GetCustomUpStreamHttpsProxyFunc
{
get
;
set
;
}
/// <summary>
...
...
@@ -383,6 +398,7 @@ namespace Titanium.Web.Proxy
//Other errors are discarded to keep proxy running
}
if
(
tcpClient
!=
null
)
{
Task
.
Run
(
async
()
=>
...
...
@@ -395,15 +411,9 @@ namespace Titanium.Web.Proxy
}
else
{
ExternalProxy
externalHttpProxy
=
null
;
if
(
GetCustomUpStreamHttpProxyFunc
!=
null
)
externalHttpProxy
=
GetCustomUpStreamHttpProxyFunc
();
ExternalProxy
externalHttpsProxy
=
null
;
if
(
GetCustomUpStreamHttpsProxyFunc
!=
null
)
externalHttpsProxy
=
GetCustomUpStreamHttpsProxyFunc
();
await
HandleClient
(
endPoint
as
ExplicitProxyEndPoint
,
tcpClient
,
externalHttpProxy
,
externalHttpsProxy
);
await
HandleClient
(
endPoint
as
ExplicitProxyEndPoint
,
tcpClient
);
}
}
finally
...
...
Titanium.Web.Proxy/RequestHandler.cs
View file @
4c75ae15
...
...
@@ -15,6 +15,7 @@ using Titanium.Web.Proxy.Shared;
using
Titanium.Web.Proxy.Http
;
using
System.Threading.Tasks
;
using
Titanium.Web.Proxy.Extensions
;
using
System.Text
;
namespace
Titanium.Web.Proxy
{
...
...
@@ -23,9 +24,87 @@ namespace Titanium.Web.Proxy
/// </summary>
partial
class
ProxyServer
{
private
async
Task
<
bool
>
CheckAuthorization
(
StreamWriter
clientStreamWriter
,
IEnumerable
<
HttpHeader
>
Headers
)
{
if
(
AuthenticateUserFunc
==
null
)
{
return
true
;
}
try
{
if
(!
Headers
.
Where
(
t
=>
t
.
Name
==
"Proxy-Authorization"
).
Any
())
{
await
WriteResponseStatus
(
new
Version
(
1
,
1
),
"407"
,
"Proxy Authentication Required"
,
clientStreamWriter
);
var
response
=
new
Response
();
response
.
ResponseHeaders
=
new
Dictionary
<
string
,
HttpHeader
>();
response
.
ResponseHeaders
.
Add
(
"Proxy-Authenticate"
,
new
HttpHeader
(
"Proxy-Authenticate"
,
"Basic realm=\"TitaniumProxy\""
));
response
.
ResponseHeaders
.
Add
(
"Proxy-Connection"
,
new
HttpHeader
(
"Proxy-Connection"
,
"close"
));
await
WriteResponseHeaders
(
clientStreamWriter
,
response
);
await
clientStreamWriter
.
WriteLineAsync
();
return
false
;
}
else
{
var
headerValue
=
Headers
.
Where
(
t
=>
t
.
Name
==
"Proxy-Authorization"
).
FirstOrDefault
().
Value
.
Trim
();
if
(!
headerValue
.
ToLower
().
StartsWith
(
"basic"
))
{
//Return not authorized
await
WriteResponseStatus
(
new
Version
(
1
,
1
),
"407"
,
"Proxy Authentication Invalid"
,
clientStreamWriter
);
var
response
=
new
Response
();
response
.
ResponseHeaders
=
new
Dictionary
<
string
,
HttpHeader
>();
response
.
ResponseHeaders
.
Add
(
"Proxy-Authenticate"
,
new
HttpHeader
(
"Proxy-Authenticate"
,
"Basic realm=\"TitaniumProxy\""
));
response
.
ResponseHeaders
.
Add
(
"Proxy-Connection"
,
new
HttpHeader
(
"Proxy-Connection"
,
"close"
));
await
WriteResponseHeaders
(
clientStreamWriter
,
response
);
await
clientStreamWriter
.
WriteLineAsync
();
return
false
;
}
headerValue
=
headerValue
.
Substring
(
5
).
Trim
();
var
decoded
=
Encoding
.
UTF8
.
GetString
(
Convert
.
FromBase64String
(
headerValue
));
if
(
decoded
.
Contains
(
":"
)
==
false
)
{
//Return not authorized
await
WriteResponseStatus
(
new
Version
(
1
,
1
),
"407"
,
"Proxy Authentication Invalid"
,
clientStreamWriter
);
var
response
=
new
Response
();
response
.
ResponseHeaders
=
new
Dictionary
<
string
,
HttpHeader
>();
response
.
ResponseHeaders
.
Add
(
"Proxy-Authenticate"
,
new
HttpHeader
(
"Proxy-Authenticate"
,
"Basic realm=\"TitaniumProxy\""
));
response
.
ResponseHeaders
.
Add
(
"Proxy-Connection"
,
new
HttpHeader
(
"Proxy-Connection"
,
"close"
));
await
WriteResponseHeaders
(
clientStreamWriter
,
response
);
await
clientStreamWriter
.
WriteLineAsync
();
return
false
;
}
var
username
=
decoded
.
Substring
(
0
,
decoded
.
IndexOf
(
':'
));
var
password
=
decoded
.
Substring
(
decoded
.
IndexOf
(
':'
)
+
1
);
return
await
AuthenticateUserFunc
(
username
,
password
).
ConfigureAwait
(
false
);
}
}
catch
(
Exception
e
)
{
//Return not authorized
await
WriteResponseStatus
(
new
Version
(
1
,
1
),
"407"
,
"Proxy Authentication Invalid"
,
clientStreamWriter
);
var
response
=
new
Response
();
response
.
ResponseHeaders
=
new
Dictionary
<
string
,
HttpHeader
>();
response
.
ResponseHeaders
.
Add
(
"Proxy-Authenticate"
,
new
HttpHeader
(
"Proxy-Authenticate"
,
"Basic realm=\"TitaniumProxy\""
));
response
.
ResponseHeaders
.
Add
(
"Proxy-Connection"
,
new
HttpHeader
(
"Proxy-Connection"
,
"close"
));
await
WriteResponseHeaders
(
clientStreamWriter
,
response
);
await
clientStreamWriter
.
WriteLineAsync
();
return
false
;
}
}
//This is called when client is aware of proxy
//So for HTTPS requests client would send CONNECT header to negotiate a secure tcp tunnel via proxy
private
async
Task
HandleClient
(
ExplicitProxyEndPoint
endPoint
,
TcpClient
client
,
ExternalProxy
customUpStreamHttpProxy
=
null
,
ExternalProxy
customUpStreamHttpsProxy
=
null
)
private
async
Task
HandleClient
(
ExplicitProxyEndPoint
endPoint
,
TcpClient
client
)
{
Stream
clientStream
=
client
.
GetStream
();
...
...
@@ -81,7 +160,20 @@ namespace Titanium.Web.Proxy
if
(
httpVerb
.
ToUpper
()
==
"CONNECT"
&&
!
excluded
&&
httpRemoteUri
.
Port
!=
80
)
{
httpRemoteUri
=
new
Uri
(
"https://"
+
httpCmdSplit
[
1
]);
await
clientStreamReader
.
ReadAllLinesAsync
();
string
tmpLine
=
null
;
List
<
HttpHeader
>
headers
=
new
List
<
HttpHeader
>();
while
(!
string
.
IsNullOrEmpty
(
tmpLine
=
await
clientStreamReader
.
ReadLineAsync
()))
{
var
header
=
tmpLine
.
Split
(
ProxyConstants
.
ColonSplit
,
2
);
var
newHeader
=
new
HttpHeader
(
header
[
0
],
header
[
1
]);
headers
.
Add
(
newHeader
);
}
if
(
await
CheckAuthorization
(
clientStreamWriter
,
headers
)
==
false
)
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
return
;
}
await
WriteConnectResponse
(
clientStreamWriter
,
version
);
...
...
@@ -136,13 +228,11 @@ namespace Titanium.Web.Proxy
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
return
;
}
//Now create the request
await
HandleHttpSessionRequest
(
client
,
httpCmd
,
clientStream
,
clientStreamReader
,
clientStreamWriter
,
httpRemoteUri
.
Scheme
==
Uri
.
UriSchemeHttps
?
httpRemoteUri
.
Host
:
null
,
customUpStreamHttpProxy
,
customUpStreamHttpsProxy
);
httpRemoteUri
.
Scheme
==
Uri
.
UriSchemeHttps
?
httpRemoteUri
.
Host
:
null
,
null
,
null
);
}
catch
(
Exception
ex
)
catch
(
Exception
ex
)
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
null
);
}
...
...
@@ -250,6 +340,7 @@ namespace Titanium.Web.Proxy
}
}
//Read the request headers in to unique and non-unique header collections
string
tmpLine
;
while
(!
string
.
IsNullOrEmpty
(
tmpLine
=
await
clientStreamReader
.
ReadLineAsync
()))
...
...
@@ -295,6 +386,15 @@ namespace Titanium.Web.Proxy
args
.
ProxyClient
.
ClientStreamReader
=
clientStreamReader
;
args
.
ProxyClient
.
ClientStreamWriter
=
clientStreamWriter
;
if
(
httpsHostName
==
null
&&
(
await
CheckAuthorization
(
clientStreamWriter
,
args
.
WebSession
.
Request
.
RequestHeaders
.
Values
)
==
false
))
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
args
);
break
;
}
PrepareRequestHeaders
(
args
.
WebSession
.
Request
.
RequestHeaders
,
args
.
WebSession
);
args
.
WebSession
.
Request
.
Host
=
args
.
WebSession
.
Request
.
RequestUri
.
Authority
;
...
...
@@ -328,6 +428,13 @@ namespace Titanium.Web.Proxy
//construct the web request that we are going to issue on behalf of the client.
if
(
connection
==
null
)
{
if
(
GetCustomUpStreamHttpProxyFunc
!=
null
)
customUpStreamHttpProxy
=
GetCustomUpStreamHttpProxyFunc
(
args
.
WebSession
.
Request
.
RequestHeaders
.
Values
);
if
(
GetCustomUpStreamHttpsProxyFunc
!=
null
)
customUpStreamHttpsProxy
=
GetCustomUpStreamHttpsProxyFunc
(
args
.
WebSession
.
Request
.
RequestHeaders
.
Values
);
connection
=
await
tcpConnectionFactory
.
CreateClient
(
BUFFER_SIZE
,
ConnectionTimeOutSeconds
,
args
.
WebSession
.
Request
.
RequestUri
.
Host
,
args
.
WebSession
.
Request
.
RequestUri
.
Port
,
httpVersion
,
args
.
IsHttps
,
SupportedSslProtocols
,
...
...
@@ -421,7 +528,7 @@ namespace Titanium.Web.Proxy
httpCmd
=
await
clientStreamReader
.
ReadLineAsync
();
}
catch
(
Exception
e
)
catch
(
Exception
e
)
{
Dispose
(
clientStream
,
clientStreamReader
,
clientStreamWriter
,
args
);
break
;
...
...
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