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
c41ef90a
Commit
c41ef90a
authored
Jun 27, 2017
by
justcoding121
Committed by
justcoding121
Jun 27, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #288 from honfika/develop
Parse ssl extensions
parents
22d0cfde
2ebdf9e4
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
445 additions
and
18 deletions
+445
-18
CustomBufferedPeekStream.cs
Titanium.Web.Proxy/Helpers/CustomBufferedPeekStream.cs
+2
-1
ConnectRequest.cs
Titanium.Web.Proxy/Http/ConnectRequest.cs
+15
-0
HttpsTools.cs
Titanium.Web.Proxy/Http/HttpsTools.cs
+428
-17
No files found.
Titanium.Web.Proxy/Helpers/CustomBufferedPeekStream.cs
View file @
c41ef90a
...
@@ -17,10 +17,11 @@ namespace Titanium.Web.Proxy.Helpers
...
@@ -17,10 +17,11 @@ namespace Titanium.Web.Proxy.Helpers
position
=
startPosition
;
position
=
startPosition
;
}
}
public
int
Available
=>
baseStream
.
Available
-
position
;
public
async
Task
<
bool
>
EnsureBufferLength
(
int
length
)
public
async
Task
<
bool
>
EnsureBufferLength
(
int
length
)
{
{
var
val
=
await
baseStream
.
PeekByteAsync
(
length
-
1
);
var
val
=
await
baseStream
.
PeekByteAsync
(
position
+
length
-
1
);
return
val
!=
-
1
;
return
val
!=
-
1
;
}
}
...
...
Titanium.Web.Proxy/Http/ConnectRequest.cs
View file @
c41ef90a
...
@@ -36,6 +36,12 @@ namespace Titanium.Web.Proxy.Http
...
@@ -36,6 +36,12 @@ namespace Titanium.Web.Proxy.Http
public
byte
[]
SessionId
{
get
;
set
;
}
public
byte
[]
SessionId
{
get
;
set
;
}
public
byte
[]
CiphersData
{
get
;
set
;
}
public
byte
[]
CompressionData
{
get
;
set
;
}
public
List
<
Extension
>
Extensions
{
get
;
set
;
}
private
static
string
SslVersionToString
(
int
major
,
int
minor
)
private
static
string
SslVersionToString
(
int
major
,
int
minor
)
{
{
string
str
=
"Unknown"
;
string
str
=
"Unknown"
;
...
@@ -69,6 +75,15 @@ namespace Titanium.Web.Proxy.Http
...
@@ -69,6 +75,15 @@ namespace Titanium.Web.Proxy.Http
sb
.
AppendLine
(
$"\"Time\":
{
Time
}
"
);
sb
.
AppendLine
(
$"\"Time\":
{
Time
}
"
);
sb
.
AppendLine
(
$"SessionID:
{
string
.
Join
(
" "
,
SessionId
.
Select
(
x
=>
x
.
ToString
(
"X2"
)))}
"
);
sb
.
AppendLine
(
$"SessionID:
{
string
.
Join
(
" "
,
SessionId
.
Select
(
x
=>
x
.
ToString
(
"X2"
)))}
"
);
if
(
Extensions
!=
null
)
{
sb
.
AppendLine
(
"Extensions:"
);
foreach
(
var
extension
in
Extensions
)
{
sb
.
AppendLine
(
$"
{
extension
.
Name
}
:
{
extension
.
Data
}
"
);
}
}
return
sb
.
ToString
();
return
sb
.
ToString
();
}
}
}
}
...
...
Titanium.Web.Proxy/Http/HttpsTools.cs
View file @
c41ef90a
...
@@ -45,8 +45,8 @@ namespace Titanium.Web.Proxy.Http
...
@@ -45,8 +45,8 @@ namespace Titanium.Web.Proxy.Http
var
peekStream
=
new
CustomBufferedPeekStream
(
clientStream
,
1
);
var
peekStream
=
new
CustomBufferedPeekStream
(
clientStream
,
1
);
//should contain at least 43 bytes
//should contain at least 43 bytes
int
requiredLength
=
43
;
// 2 version + 2 length + 1 type + 3 length(?) + 2 version + 32 random + 1 sessionid length
// 2 version + 2 length + 1 type + 3 length(?) + 2 version + 32 random + 1 sessionid length
if
(!
await
peekStream
.
EnsureBufferLength
(
requiredLength
))
if
(!
await
peekStream
.
EnsureBufferLength
(
43
))
{
{
return
false
;
return
false
;
}
}
...
@@ -71,8 +71,8 @@ namespace Titanium.Web.Proxy.Http
...
@@ -71,8 +71,8 @@ namespace Titanium.Web.Proxy.Http
byte
[]
random
=
peekStream
.
ReadBytes
(
32
);
byte
[]
random
=
peekStream
.
ReadBytes
(
32
);
length
=
peekStream
.
ReadByte
();
length
=
peekStream
.
ReadByte
();
requiredLength
+=
length
+
2
;
// sessionid + 2 d
ata length
// sessionid + 2 ciphersD
ata length
if
(!
await
peekStream
.
EnsureBufferLength
(
requiredLength
))
if
(!
await
peekStream
.
EnsureBufferLength
(
length
+
2
))
{
{
return
false
;
return
false
;
}
}
...
@@ -81,13 +81,13 @@ namespace Titanium.Web.Proxy.Http
...
@@ -81,13 +81,13 @@ namespace Titanium.Web.Proxy.Http
length
=
peekStream
.
ReadInt16
();
length
=
peekStream
.
ReadInt16
();
requiredLength
+=
length
+
1
;
// data + data2
length
// ciphersData + compressionData
length
if
(!
await
peekStream
.
EnsureBufferLength
(
requiredLength
))
if
(!
await
peekStream
.
EnsureBufferLength
(
length
+
1
))
{
{
return
false
;
return
false
;
}
}
byte
[]
d
ata
=
peekStream
.
ReadBytes
(
length
);
byte
[]
ciphersD
ata
=
peekStream
.
ReadBytes
(
length
);
length
=
peekStream
.
ReadByte
();
length
=
peekStream
.
ReadByte
();
if
(
length
<
1
)
if
(
length
<
1
)
...
@@ -95,26 +95,31 @@ namespace Titanium.Web.Proxy.Http
...
@@ -95,26 +95,31 @@ namespace Titanium.Web.Proxy.Http
return
false
;
return
false
;
}
}
requiredLength
+=
length
;
// data2
// compressionData
if
(!
await
peekStream
.
EnsureBufferLength
(
requiredL
ength
))
if
(!
await
peekStream
.
EnsureBufferLength
(
l
ength
))
{
{
return
false
;
return
false
;
}
}
byte
[]
data2
=
peekStream
.
ReadBytes
(
length
);
byte
[]
compressionData
=
peekStream
.
ReadBytes
(
length
);
byte
[]
data3
=
null
;
List
<
Extension
>
extensions
=
null
;
if
(
majorVersion
>
3
||
majorVersion
==
3
&&
minorVersion
>=
1
)
if
(
majorVersion
>
3
||
majorVersion
==
3
&&
minorVersion
>=
1
)
{
{
requiredLength
+=
2
;
if
(
await
peekStream
.
EnsureBufferLength
(
2
))
if
(
await
peekStream
.
EnsureBufferLength
(
requiredLength
))
{
{
length
=
peekStream
.
ReadInt16
();
length
=
peekStream
.
ReadInt16
();
requiredLength
+=
length
;
if
(
await
peekStream
.
EnsureBufferLength
(
length
))
if
(
await
peekStream
.
EnsureBufferLength
(
requiredLength
))
{
extensions
=
new
List
<
Extension
>();
while
(
peekStream
.
Available
>
3
)
{
{
data3
=
peekStream
.
ReadBytes
(
length
);
int
id
=
peekStream
.
ReadInt16
();
length
=
peekStream
.
ReadInt16
();
byte
[]
data
=
peekStream
.
ReadBytes
(
length
);
extensions
.
Add
(
GetExtension
(
id
,
data
));
}
}
}
}
}
}
}
...
@@ -125,6 +130,9 @@ namespace Titanium.Web.Proxy.Http
...
@@ -125,6 +130,9 @@ namespace Titanium.Web.Proxy.Http
MinorVersion
=
minorVersion
,
MinorVersion
=
minorVersion
,
Random
=
random
,
Random
=
random
,
SessionId
=
sessionId
,
SessionId
=
sessionId
,
CiphersData
=
ciphersData
,
CompressionData
=
compressionData
,
Extensions
=
extensions
,
};
};
return
true
;
return
true
;
...
@@ -132,5 +140,408 @@ namespace Titanium.Web.Proxy.Http
...
@@ -132,5 +140,408 @@ namespace Titanium.Web.Proxy.Http
return
false
;
return
false
;
}
}
private
static
Extension
GetExtension
(
int
value
,
byte
[]
data
)
{
string
name
=
GetExtensionName
(
value
);
string
dataStr
=
GetExtensionData
(
value
,
data
);
return
new
Extension
(
value
,
name
,
dataStr
);
}
private
static
string
GetExtensionData
(
int
value
,
byte
[]
data
)
{
//https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
switch
(
value
)
{
case
0
:
var
stringBuilder
=
new
StringBuilder
();
int
index
=
2
;
while
(
index
<
data
.
Length
)
{
int
nameType
=
data
[
index
];
int
count
=
(
data
[
index
+
1
]
<<
8
)
+
data
[
index
+
2
];
string
str
=
Encoding
.
ASCII
.
GetString
(
data
,
index
+
3
,
count
);
if
(
nameType
==
0
)
{
stringBuilder
.
AppendFormat
(
"{0}{1}"
,
stringBuilder
.
Length
>
1
?
"; "
:
string
.
Empty
,
str
);
}
index
+=
3
+
count
;
}
return
stringBuilder
.
ToString
();
case
5
:
if
(
data
.
Length
==
5
&&
data
[
0
]
==
1
&&
data
[
1
]
==
0
&&
data
[
2
]
==
0
&&
data
[
3
]
==
0
&&
data
[
4
]
==
0
)
{
return
"OCSP - Implicit Responder"
;
}
return
ByteArrayToString
(
data
);
case
10
:
return
GetSupportedGroup
(
data
);
case
11
:
return
GetEcPointFormats
(
data
);
case
13
:
return
GetSignatureAlgorithms
(
data
);
case
16
:
return
GetApplicationLayerProtocolNegotiation
(
data
);
case
35655
:
return
$"
{
data
.
Length
}
bytes"
;
default
:
return
ByteArrayToString
(
data
);
}
}
private
static
string
GetSupportedGroup
(
byte
[]
data
)
{
//https://datatracker.ietf.org/doc/draft-ietf-tls-rfc4492bis/?include_text=1
List
<
string
>
list
=
new
List
<
string
>();
if
(
data
.
Length
<
2
)
{
return
string
.
Empty
;
}
int
i
=
2
;
while
(
i
<
data
.
Length
-
1
)
{
int
namedCurve
=
(
data
[
i
]
<<
8
)
+
data
[
i
+
1
];
switch
(
namedCurve
)
{
case
1
:
list
.
Add
(
"sect163k1 [0x1]"
);
//deprecated
break
;
case
2
:
list
.
Add
(
"sect163r1 [0x2]"
);
//deprecated
break
;
case
3
:
list
.
Add
(
"sect163r2 [0x3]"
);
//deprecated
break
;
case
4
:
list
.
Add
(
"sect193r1 [0x4]"
);
//deprecated
break
;
case
5
:
list
.
Add
(
"sect193r2 [0x5]"
);
//deprecated
break
;
case
6
:
list
.
Add
(
"sect233k1 [0x6]"
);
//deprecated
break
;
case
7
:
list
.
Add
(
"sect233r1 [0x7]"
);
//deprecated
break
;
case
8
:
list
.
Add
(
"sect239k1 [0x8]"
);
//deprecated
break
;
case
9
:
list
.
Add
(
"sect283k1 [0x9]"
);
//deprecated
break
;
case
10
:
list
.
Add
(
"sect283r1 [0xA]"
);
//deprecated
break
;
case
11
:
list
.
Add
(
"sect409k1 [0xB]"
);
//deprecated
break
;
case
12
:
list
.
Add
(
"sect409r1 [0xC]"
);
//deprecated
break
;
case
13
:
list
.
Add
(
"sect571k1 [0xD]"
);
//deprecated
break
;
case
14
:
list
.
Add
(
"sect571r1 [0xE]"
);
//deprecated
break
;
case
15
:
list
.
Add
(
"secp160k1 [0xF]"
);
//deprecated
break
;
case
16
:
list
.
Add
(
"secp160r1 [0x10]"
);
//deprecated
break
;
case
17
:
list
.
Add
(
"secp160r2 [0x11]"
);
//deprecated
break
;
case
18
:
list
.
Add
(
"secp192k1 [0x12]"
);
//deprecated
break
;
case
19
:
list
.
Add
(
"secp192r1 [0x13]"
);
//deprecated
break
;
case
20
:
list
.
Add
(
"secp224k1 [0x14]"
);
//deprecated
break
;
case
21
:
list
.
Add
(
"secp224r1 [0x15]"
);
//deprecated
break
;
case
22
:
list
.
Add
(
"secp256k1 [0x16]"
);
//deprecated
break
;
case
23
:
list
.
Add
(
"secp256r1 [0x17]"
);
break
;
case
24
:
list
.
Add
(
"secp384r1 [0x18]"
);
break
;
case
25
:
list
.
Add
(
"secp521r1 [0x19]"
);
break
;
case
26
:
list
.
Add
(
"brainpoolP256r1 [0x1A]"
);
break
;
case
27
:
list
.
Add
(
"brainpoolP384r1 [0x1B]"
);
break
;
case
28
:
list
.
Add
(
"brainpoolP512r1 [0x1C]"
);
break
;
case
29
:
list
.
Add
(
"x25519 [0x1D]"
);
break
;
case
30
:
list
.
Add
(
"x448 [0x1E]"
);
break
;
case
256
:
list
.
Add
(
"ffdhe2048 [0x0100]"
);
break
;
case
257
:
list
.
Add
(
"ffdhe3072 [0x0101]"
);
break
;
case
258
:
list
.
Add
(
"ffdhe4096 [0x0102]"
);
break
;
case
259
:
list
.
Add
(
"ffdhe6144 [0x0103]"
);
break
;
case
260
:
list
.
Add
(
"ffdhe8192 [0x0104]"
);
break
;
case
65281
:
list
.
Add
(
"arbitrary_explicit_prime_curves [0xFF01]"
);
//deprecated
break
;
case
65282
:
list
.
Add
(
"arbitrary_explicit_char2_curves [0xFF02]"
);
//deprecated
break
;
default
:
list
.
Add
(
$"unknown [0x
{
namedCurve
:
X4
}
]"
);
break
;
}
i
+=
2
;
}
return
string
.
Join
(
", "
,
list
.
ToArray
());
}
private
static
string
GetEcPointFormats
(
byte
[]
data
)
{
List
<
string
>
list
=
new
List
<
string
>();
if
(
data
.
Length
<
1
)
{
return
string
.
Empty
;
}
int
i
=
1
;
while
(
i
<
data
.
Length
)
{
switch
(
data
[
i
])
{
case
0
:
list
.
Add
(
"uncompressed [0x0]"
);
break
;
case
1
:
list
.
Add
(
"ansiX962_compressed_prime [0x1]"
);
break
;
case
2
:
list
.
Add
(
"ansiX962_compressed_char2 [0x2]"
);
break
;
default
:
list
.
Add
(
$"unknown [0x
{
data
[
i
]:
X2
}
]"
);
break
;
}
i
+=
2
;
}
return
string
.
Join
(
", "
,
list
.
ToArray
());
}
private
static
string
GetSignatureAlgorithms
(
byte
[]
data
)
{
// https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
int
num
=
(
data
[
0
]
<<
8
)
+
data
[
1
];
var
sb
=
new
StringBuilder
();
int
index
=
2
;
while
(
index
<
num
+
2
)
{
switch
(
data
[
index
])
{
case
0
:
sb
.
Append
(
"none"
);
break
;
case
1
:
sb
.
Append
(
"md5"
);
break
;
case
2
:
sb
.
Append
(
"sha1"
);
break
;
case
3
:
sb
.
Append
(
"sha224"
);
break
;
case
4
:
sb
.
Append
(
"sha256"
);
break
;
case
5
:
sb
.
Append
(
"sha384"
);
break
;
case
6
:
sb
.
Append
(
"sha512"
);
break
;
case
8
:
sb
.
Append
(
"Intrinsic"
);
break
;
default
:
sb
.
AppendFormat
(
"Unknown[0x{0:X2}]"
,
data
[
index
]);
break
;
}
sb
.
AppendFormat
(
"_"
);
switch
(
data
[
index
+
1
])
{
case
0
:
sb
.
Append
(
"anonymous"
);
break
;
case
1
:
sb
.
Append
(
"rsa"
);
break
;
case
2
:
sb
.
Append
(
"dsa"
);
break
;
case
3
:
sb
.
Append
(
"ecdsa"
);
break
;
case
7
:
sb
.
Append
(
"ed25519"
);
break
;
case
8
:
sb
.
Append
(
"ed448"
);
break
;
default
:
sb
.
AppendFormat
(
"Unknown[0x{0:X2}]"
,
data
[
index
+
1
]);
break
;
}
sb
.
AppendFormat
(
", "
);
index
+=
2
;
}
if
(
sb
.
Length
>
1
)
sb
.
Length
-=
2
;
return
sb
.
ToString
();
}
private
static
string
GetApplicationLayerProtocolNegotiation
(
byte
[]
data
)
{
List
<
string
>
stringList
=
new
List
<
string
>();
int
index
=
2
;
while
(
index
<
data
.
Length
)
{
int
count
=
data
[
index
];
stringList
.
Add
(
Encoding
.
ASCII
.
GetString
(
data
,
index
+
1
,
count
));
index
+=
1
+
count
;
}
return
string
.
Join
(
", "
,
stringList
.
ToArray
());
}
private
static
string
GetExtensionName
(
int
value
)
{
//https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
switch
(
value
)
{
case
0
:
return
"server_name"
;
case
1
:
return
"max_fragment_length"
;
case
2
:
return
"client_certificate_url"
;
case
3
:
return
"trusted_ca_keys"
;
case
4
:
return
"truncated_hmac"
;
case
5
:
return
"status_request"
;
case
6
:
return
"user_mapping"
;
case
7
:
return
"client_authz"
;
case
8
:
return
"server_authz"
;
case
9
:
return
"cert_type"
;
case
10
:
return
"supported_groups"
;
// renamed from "elliptic_curves"
case
11
:
return
"ec_point_formats"
;
case
12
:
return
"srp"
;
case
13
:
return
"signature_algorithms"
;
case
14
:
return
"use_srtp"
;
case
15
:
return
"heartbeat"
;
case
16
:
return
"ALPN"
;
// application_layer_protocol_negotiation
case
17
:
return
"status_request_v2"
;
case
18
:
return
"signed_certificate_timestamp"
;
case
19
:
return
"client_certificate_type"
;
case
20
:
return
"server_certificate_type"
;
case
21
:
return
"padding"
;
case
22
:
return
"encrypt_then_mac"
;
case
23
:
return
"extended_master_secret"
;
case
24
:
return
"token_binding"
;
// TEMPORARY - registered 2016-02-04, extension registered 2017-01-12, expires 2018-02-04
case
25
:
return
"cached_info"
;
case
35
:
return
"SessionTicket TLS"
;
case
13172
:
return
"next_protocol_negotiation"
;
case
30031
:
case
30032
:
return
"channel_id"
;
// Google
case
35655
:
return
"draft-agl-tls-padding"
;
case
65281
:
return
"renegotiation_info"
;
default
:
return
"unknown"
;
}
}
private
static
string
ByteArrayToString
(
byte
[]
data
)
{
return
string
.
Join
(
" "
,
data
.
Select
(
x
=>
x
.
ToString
(
"X2"
)));
}
}
public
class
Extension
{
public
int
Value
{
get
;
set
;
}
public
string
Name
{
get
;
set
;
}
public
string
Data
{
get
;
set
;
}
public
Extension
(
int
value
,
string
name
,
string
data
)
{
Value
=
value
;
Name
=
name
;
Data
=
data
;
}
}
}
}
}
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