|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+package faketls_test
|
|
|
2
|
+
|
|
|
3
|
+import (
|
|
|
4
|
+ "encoding/base64"
|
|
|
5
|
+ "encoding/json"
|
|
|
6
|
+ "os"
|
|
|
7
|
+ "path/filepath"
|
|
|
8
|
+ "strings"
|
|
|
9
|
+ "testing"
|
|
|
10
|
+ "time"
|
|
|
11
|
+
|
|
|
12
|
+ "github.com/9seconds/mtg/v2/mtglib"
|
|
|
13
|
+ "github.com/9seconds/mtg/v2/mtglib/internal/faketls"
|
|
|
14
|
+ "github.com/stretchr/testify/assert"
|
|
|
15
|
+ "github.com/stretchr/testify/suite"
|
|
|
16
|
+)
|
|
|
17
|
+
|
|
|
18
|
+type ClientHelloSnapshot struct {
|
|
|
19
|
+ Time int `json:"time"`
|
|
|
20
|
+ Random string `json:"random"`
|
|
|
21
|
+ SessionID string `json:"session-id"`
|
|
|
22
|
+ Host string `json:"host"`
|
|
|
23
|
+ CipherSuite int `json:"cipher-suite"`
|
|
|
24
|
+ Full string `json:"full"`
|
|
|
25
|
+}
|
|
|
26
|
+
|
|
|
27
|
+func (c ClientHelloSnapshot) GetTime() time.Time {
|
|
|
28
|
+ return time.Unix(int64(c.Time), 0)
|
|
|
29
|
+}
|
|
|
30
|
+
|
|
|
31
|
+func (c ClientHelloSnapshot) GetRandom() []byte {
|
|
|
32
|
+ data, _ := base64.StdEncoding.DecodeString(c.Random)
|
|
|
33
|
+
|
|
|
34
|
+ return data
|
|
|
35
|
+}
|
|
|
36
|
+
|
|
|
37
|
+func (c ClientHelloSnapshot) GetSessionID() []byte {
|
|
|
38
|
+ data, _ := base64.StdEncoding.DecodeString(c.SessionID)
|
|
|
39
|
+
|
|
|
40
|
+ return data
|
|
|
41
|
+}
|
|
|
42
|
+
|
|
|
43
|
+func (c ClientHelloSnapshot) GetHost() string {
|
|
|
44
|
+ return c.Host
|
|
|
45
|
+}
|
|
|
46
|
+
|
|
|
47
|
+func (c ClientHelloSnapshot) GetCipherSuite() uint16 {
|
|
|
48
|
+ return uint16(c.CipherSuite)
|
|
|
49
|
+}
|
|
|
50
|
+
|
|
|
51
|
+func (c ClientHelloSnapshot) GetFull() []byte {
|
|
|
52
|
+ data, _ := base64.StdEncoding.DecodeString(c.Full)
|
|
|
53
|
+
|
|
|
54
|
+ return data
|
|
|
55
|
+}
|
|
|
56
|
+
|
|
|
57
|
+type ClientHelloTestSuite struct {
|
|
|
58
|
+ suite.Suite
|
|
|
59
|
+
|
|
|
60
|
+ secret mtglib.Secret
|
|
|
61
|
+}
|
|
|
62
|
+
|
|
|
63
|
+func (suite *ClientHelloTestSuite) SetupSuite() {
|
|
|
64
|
+ parsed, err := mtglib.ParseSecret("ee367a189aee18fa31c190054efd4a8e9573746f726167652e676f6f676c65617069732e636f6d")
|
|
|
65
|
+ if err != nil {
|
|
|
66
|
+ panic(err)
|
|
|
67
|
+ }
|
|
|
68
|
+
|
|
|
69
|
+ suite.secret = parsed
|
|
|
70
|
+}
|
|
|
71
|
+
|
|
|
72
|
+func (suite *ClientHelloTestSuite) TestEmptyHandshake() {
|
|
|
73
|
+ _, err := faketls.ParseClientHello(suite.secret.Key[:], nil)
|
|
|
74
|
+ suite.Error(err)
|
|
|
75
|
+}
|
|
|
76
|
+
|
|
|
77
|
+func (suite *ClientHelloTestSuite) TestIncorrectHandshakeType() {
|
|
|
78
|
+ data := make([]byte, 1024)
|
|
|
79
|
+ data[0] = 0x02
|
|
|
80
|
+
|
|
|
81
|
+ _, err := faketls.ParseClientHello(suite.secret.Key[:], data)
|
|
|
82
|
+ suite.Error(err)
|
|
|
83
|
+}
|
|
|
84
|
+
|
|
|
85
|
+func (suite *ClientHelloTestSuite) TestIncorrectLength() {
|
|
|
86
|
+ data := make([]byte, 1024)
|
|
|
87
|
+ data[0] = 0x01
|
|
|
88
|
+ data[1] = 0xff
|
|
|
89
|
+ data[2] = 0xff
|
|
|
90
|
+
|
|
|
91
|
+ _, err := faketls.ParseClientHello(suite.secret.Key[:], data)
|
|
|
92
|
+ suite.Error(err)
|
|
|
93
|
+}
|
|
|
94
|
+
|
|
|
95
|
+func (suite *ClientHelloTestSuite) TestSnapshotOk() {
|
|
|
96
|
+ files, err := os.ReadDir("testdata")
|
|
|
97
|
+ suite.NoError(err)
|
|
|
98
|
+
|
|
|
99
|
+ testData := []string{}
|
|
|
100
|
+
|
|
|
101
|
+ for _, v := range files {
|
|
|
102
|
+ if strings.HasPrefix(v.Name(), "client-hello-ok") {
|
|
|
103
|
+ testData = append(testData, v.Name())
|
|
|
104
|
+ }
|
|
|
105
|
+ }
|
|
|
106
|
+
|
|
|
107
|
+ for _, name := range testData {
|
|
|
108
|
+ path := filepath.Join("testdata", name)
|
|
|
109
|
+
|
|
|
110
|
+ suite.T().Run(name, func(t *testing.T) {
|
|
|
111
|
+ fileData, err := os.ReadFile(path)
|
|
|
112
|
+ assert.NoError(t, err)
|
|
|
113
|
+
|
|
|
114
|
+ snapshot := &ClientHelloSnapshot{}
|
|
|
115
|
+ assert.NoError(t, json.Unmarshal(fileData, snapshot))
|
|
|
116
|
+
|
|
|
117
|
+ hello, err := faketls.ParseClientHello(suite.secret.Key[:], snapshot.GetFull())
|
|
|
118
|
+ assert.NoError(t, err)
|
|
|
119
|
+ assert.WithinDuration(t, snapshot.GetTime(), hello.Time, time.Second)
|
|
|
120
|
+ assert.Equal(t, snapshot.GetRandom(), hello.Random[:])
|
|
|
121
|
+ assert.Equal(t, snapshot.GetSessionID(), hello.SessionID)
|
|
|
122
|
+ assert.Equal(t, snapshot.GetHost(), hello.Host)
|
|
|
123
|
+ assert.Equal(t, snapshot.GetCipherSuite(), hello.CipherSuite)
|
|
|
124
|
+ })
|
|
|
125
|
+ }
|
|
|
126
|
+}
|
|
|
127
|
+
|
|
|
128
|
+func (suite *ClientHelloTestSuite) TestSnapshotBad() {
|
|
|
129
|
+ files, err := os.ReadDir("testdata")
|
|
|
130
|
+ suite.NoError(err)
|
|
|
131
|
+
|
|
|
132
|
+ testData := []string{}
|
|
|
133
|
+
|
|
|
134
|
+ for _, v := range files {
|
|
|
135
|
+ if strings.HasPrefix(v.Name(), "client-hello-bad") {
|
|
|
136
|
+ testData = append(testData, v.Name())
|
|
|
137
|
+ }
|
|
|
138
|
+ }
|
|
|
139
|
+
|
|
|
140
|
+ for _, name := range testData {
|
|
|
141
|
+ path := filepath.Join("testdata", name)
|
|
|
142
|
+
|
|
|
143
|
+ suite.T().Run(name, func(t *testing.T) {
|
|
|
144
|
+ fileData, err := os.ReadFile(path)
|
|
|
145
|
+ assert.NoError(t, err)
|
|
|
146
|
+
|
|
|
147
|
+ snapshot := &ClientHelloSnapshot{}
|
|
|
148
|
+ assert.NoError(t, json.Unmarshal(fileData, snapshot))
|
|
|
149
|
+
|
|
|
150
|
+ _, err = faketls.ParseClientHello(suite.secret.Key[:], snapshot.GetFull())
|
|
|
151
|
+ assert.Error(t, err)
|
|
|
152
|
+ })
|
|
|
153
|
+ }
|
|
|
154
|
+}
|
|
|
155
|
+
|
|
|
156
|
+func TestClientHello(t *testing.T) {
|
|
|
157
|
+ t.Parallel()
|
|
|
158
|
+ suite.Run(t, &ClientHelloTestSuite{})
|
|
|
159
|
+}
|