@@ -2,6 +2,7 @@ package layers
2
2
3
3
import (
4
4
"encoding/binary"
5
+ "encoding/hex"
5
6
"fmt"
6
7
"strings"
7
8
)
@@ -12,22 +13,29 @@ const (
12
13
ClientHelloTLSVal = 0x01
13
14
)
14
15
16
+ type TLSVersion struct {
17
+ Value uint16
18
+ Desc string
19
+ }
20
+
21
+ func (tv * TLSVersion ) String () string {
22
+ return fmt .Sprintf ("%s (%#04x)" , tv .Desc , tv .Value )
23
+ }
24
+
15
25
type Record struct {
16
26
ContentType uint8
17
27
ContentTypeDesc string
18
- Version uint16
19
- VersionDesc string
28
+ Version * TLSVersion
20
29
Length uint16
21
30
Data []byte
22
31
}
23
32
24
33
func (r * Record ) String () string {
25
34
return fmt .Sprintf (` - Content Type: %s (%d)
26
- - Version: %s (%#04x)
35
+ - Version: %s
27
36
- Length: %d` ,
28
37
r .ContentTypeDesc ,
29
38
r .ContentType ,
30
- r .VersionDesc ,
31
39
r .Version ,
32
40
r .Length )
33
41
}
@@ -40,6 +48,8 @@ func HSTLSParserByType(hstype uint8) HSTLSParser {
40
48
switch hstype {
41
49
case 1 :
42
50
return & TLSClientHello {}
51
+ case 2 :
52
+ return & TLSServerHello {}
43
53
}
44
54
return nil
45
55
}
@@ -53,13 +63,22 @@ func (cs *CipherSuite) String() string {
53
63
return fmt .Sprintf ("%s (%#x)" , cs .Desc , cs .Value )
54
64
}
55
65
66
+ type Extension struct {
67
+ Value uint16
68
+ Desc string
69
+ }
70
+
71
+ func (e * Extension ) String () string {
72
+ return fmt .Sprintf ("%s (%d)" , e .Desc , e .Value )
73
+ }
74
+
56
75
type ServerName struct {
57
76
Type uint16
58
77
Length uint16
59
78
SNListLength uint16
60
79
SNType uint8
61
80
SNNameLength uint16
62
- SNName [] byte
81
+ SNName string
63
82
}
64
83
65
84
func (sn * ServerName ) Parse (data []byte ) error {
@@ -68,24 +87,25 @@ func (sn *ServerName) Parse(data []byte) error {
68
87
sn .SNListLength = binary .BigEndian .Uint16 (data [4 :6 ])
69
88
sn .SNType = data [6 ]
70
89
sn .SNNameLength = binary .BigEndian .Uint16 (data [7 :9 ])
71
- sn .SNName = data [9 : 9 + sn .SNNameLength ]
90
+ sn .SNName = string ( data [9 : 9 + sn .SNNameLength ])
72
91
return nil
73
92
}
74
93
75
94
// https://wiki.osdev.org/TLS_Handshake#Client_Hello_Message
76
95
type TLSClientHello struct {
77
96
Length int // 3 bytes int(uint(b[2]) | uint(b[1])<<8 | uint(b[0])<<16))
78
- Version uint16
79
- VersionDesc string
97
+ Version * TLSVersion
80
98
Random []byte //32 bytes
81
99
SessionIDLength uint8 // if 0 no session follows
82
- SessionID [] byte
100
+ SessionID string
83
101
CipherSuitesLength uint16
84
102
CipherSuites []* CipherSuite
85
103
CmprMethodsLength uint8 // usually 0x01
86
104
CmprMethods []byte // usually 0x00
87
105
ExtensionLength uint16
106
+ Extensions []* Extension
88
107
ServerName * ServerName
108
+ ALPN []string
89
109
}
90
110
91
111
func (tch * TLSClientHello ) ParseHS (data []byte ) error {
@@ -97,12 +117,12 @@ func (tch *TLSClientHello) ParseHS(data []byte) error {
97
117
if len (data )- 4 < tch .Length {
98
118
return fmt .Errorf ("message should be at least %d bytes, got %d bytes" , tch .Length , len (data )- 4 )
99
119
}
100
- tch . Version = binary .BigEndian .Uint16 (data [4 :6 ]) // 9 - 10 bytes data[4:6]
101
- tch .VersionDesc = verdesc (tch . Version )
120
+ ver : = binary .BigEndian .Uint16 (data [4 :6 ]) // 9 - 10 bytes data[4:6]
121
+ tch .Version = & TLSVersion { Value : ver , Desc : verdesc (ver )}
102
122
tch .Random = data [6 :38 ] // 11-42 data[6:38]
103
123
tch .SessionIDLength = data [38 ] // 43 data[38] 32 bytes
104
124
sid := tch .SessionIDLength + 39 // 70
105
- tch .SessionID = data [39 :sid ] // data[39:71]
125
+ tch .SessionID = hex . EncodeToString ( data [39 :sid ]) // data[39:71]
106
126
csl := binary .BigEndian .Uint16 (data [sid : sid + 2 ]) // data[71:73] suites count * 2 bytes
107
127
tch .CipherSuitesLength = csl
108
128
offset := uint16 (sid + 2 ) //73
@@ -123,36 +143,88 @@ func (tch *TLSClientHello) ParseHS(data []byte) error {
123
143
extlen := binary .BigEndian .Uint16 (data [extoffset : extoffset + 2 ]) // data[109:111]
124
144
tch .ExtensionLength = extlen
125
145
i = extoffset + 2
146
+ exts := make ([]* Extension , 0 , 20 )
126
147
for i < extoffset + extlen {
127
148
typ := binary .BigEndian .Uint16 (data [i : i + 2 ])
128
149
length := binary .BigEndian .Uint16 (data [i + 2 : i + 4 ])
150
+ exts = append (exts , & Extension {Value : typ , Desc : extdesc (typ )})
129
151
switch typ {
130
- case 0 : // TODO: add more extensions
152
+ case 0 : // SNI
131
153
sn := & ServerName {}
132
154
err := sn .Parse (data [i : i + length + 4 ])
133
155
if err != nil {
134
156
return err
135
157
}
136
158
tch .ServerName = sn
137
- i += length + 4
138
- default :
139
- i += length + 4
159
+ case 16 : //ALPN
160
+ //skip data[i+4:i+6] alpn extension length
161
+ start := i + 6
162
+ alpns := make ([]string , 0 , 5 )
163
+ for start < i + length + 4 {
164
+ alpnStringLength := data [start ]
165
+ nextProto := string (data [start + 1 : start + uint16 (alpnStringLength + 1 )])
166
+ alpns = append (alpns , nextProto )
167
+ start += uint16 (alpnStringLength + 1 )
168
+ }
169
+ tch .ALPN = alpns
140
170
}
171
+ i += length + 4
141
172
}
173
+ tch .Extensions = exts
142
174
return nil
143
175
}
144
176
145
177
// https://wiki.osdev.org/TLS_Handshake#Server_Hello_Message
146
178
type TLSServerHello struct {
147
- Length int // 3 bytes int(uint(b[2]) | uint(b[1])<<8 | uint(b[0])<<16))
148
- Version uint16
149
- VersionDesc string
150
- Random []byte //32 bytes
151
- SessionIDLength uint8 // if 0 no session follows
152
- SessionID []byte
153
- CipherSuite * CipherSuite
154
- CmprMethod uint8
155
- ExtensionLength uint16
179
+ Length int // 3 bytes int(uint(b[2]) | uint(b[1])<<8 | uint(b[0])<<16))
180
+ Version * TLSVersion
181
+ Random []byte //32 bytes
182
+ SessionIDLength uint8 // if 0 no session follows
183
+ SessionID string
184
+ CipherSuite * CipherSuite
185
+ CmprMethod uint8
186
+ ExtensionLength uint16
187
+ Extensions []* Extension
188
+ SupportedVersion * TLSVersion
189
+ }
190
+
191
+ func (tsh * TLSServerHello ) ParseHS (data []byte ) error {
192
+ // offset 7 bytes
193
+ if len (data ) < 4 {
194
+ return fmt .Errorf ("message should be at least 4 bytes, got %d bytes" , len (data ))
195
+ }
196
+ tsh .Length = int (uint (data [3 ]) | uint (data [2 ])<< 8 | uint (data [1 ])<< 16 ) // 6 - 8 bytes data[1:4]
197
+ if len (data )- 4 < tsh .Length {
198
+ return fmt .Errorf ("message should be at least %d bytes, got %d bytes" , tsh .Length , len (data )- 4 )
199
+ }
200
+ ver := binary .BigEndian .Uint16 (data [4 :6 ]) // 9 - 10 bytes data[4:6]
201
+ tsh .Version = & TLSVersion {Value : ver , Desc : verdesc (ver )}
202
+ tsh .Random = data [6 :38 ] // 11-42 data[6:38]
203
+ tsh .SessionIDLength = data [38 ] // 43 data[38] 32 bytes
204
+ sid := tsh .SessionIDLength + 39 // 70
205
+ tsh .SessionID = hex .EncodeToString (data [39 :sid ]) // data[39:71]
206
+ val := binary .BigEndian .Uint16 (data [sid : sid + 2 ])
207
+ valdesc := csuitedesc (val )
208
+ tsh .CipherSuite = & CipherSuite {Value : val , Desc : valdesc }
209
+ tsh .CmprMethod = data [sid + 2 ]
210
+ extoffset := uint16 (sid + 3 )
211
+ extlen := binary .BigEndian .Uint16 (data [extoffset : extoffset + 2 ])
212
+ tsh .ExtensionLength = extlen
213
+ exts := make ([]* Extension , 0 , 20 )
214
+ i := extoffset + 2
215
+ for i < extoffset + extlen {
216
+ typ := binary .BigEndian .Uint16 (data [i : i + 2 ])
217
+ length := binary .BigEndian .Uint16 (data [i + 2 : i + 4 ])
218
+ exts = append (exts , & Extension {Value : typ , Desc : extdesc (typ )})
219
+ switch typ {
220
+ case 43 : // supported versions
221
+ ver := binary .BigEndian .Uint16 (data [i + 4 : i + 6 ])
222
+ tsh .SupportedVersion = & TLSVersion {Value : ver , Desc : verdesc (ver )}
223
+ }
224
+ i += length + 4
225
+ }
226
+ tsh .Extensions = exts
227
+ return nil
156
228
}
157
229
158
230
// port 443
@@ -181,7 +253,7 @@ func (t *TLSMessage) Summary() string {
181
253
sb .WriteString (fmt .Sprintf ("%s (%d) Len: %d " , rec .ContentTypeDesc , rec .ContentType , rec .Length ))
182
254
continue
183
255
}
184
- sb .WriteString (fmt . Sprintf ( "%s (%#04x) " , rec .VersionDesc , rec . Version ))
256
+ sb .WriteString (rec .Version . String ( ))
185
257
if rec .ContentType == 22 {
186
258
hstd := hstypedesc (rec .Data [0 ])
187
259
sb .WriteString (fmt .Sprintf ("%s " , hstd ))
@@ -230,8 +302,7 @@ func (t *TLSMessage) Parse(data []byte) error {
230
302
r := & Record {
231
303
ContentType : ctype ,
232
304
ContentTypeDesc : ctdesc ,
233
- Version : ver ,
234
- VersionDesc : verdesc ,
305
+ Version : & TLSVersion {Value : ver , Desc : verdesc },
235
306
Length : rlen ,
236
307
Data : data [headerSizeTLS : headerSizeTLS + rlen ],
237
308
}
0 commit comments