-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathopClienthello.go
88 lines (75 loc) · 2.06 KB
/
opClienthello.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package main
import (
"encoding/base64"
"math/rand"
"strings"
"go.uber.org/zap"
)
type xhelloObj struct {
Cipher *string `json:"cipher"`
}
type xhelloPacket struct {
Type string `json:"type"`
Obj xhelloObj `json:"obj"`
}
func opClienthello(c *ntcpclient, packet xhelloPacket) {
if packet.Obj.Cipher == nil {
c.Respond("Invalid packet. '.obj.cipher' missing")
return
}
var plain string
if envDisableCrypt {
plain = *packet.Obj.Cipher
} else {
buf, err := base64.RawStdEncoding.DecodeString(*packet.Obj.Cipher)
if err != nil {
c.Respond("Invalid packet. '.obj.cipher' must be a base64 string")
return
}
plainBuf, err := c.Crypt.Decrypt(buf)
if err != nil {
c.Log.Warn("failed to decrypt", zap.Error(err))
c.Respond("Invalid cipher text - unable to decrypt")
return
}
plain = string(plainBuf)
}
if !strings.HasPrefix(plain, "clienthello:") || strings.Count(plain, ":") != 1 {
c.Respond("Invalid plain text - expecting 'clienthello:YOURCHALLENGE'")
return
} else if plain == "clienthello:YOURCHALLENGE" {
c.Respond("Invalid server challenge in '.obj.cipher' - 'YOURCHALLENGE' is not allowed")
return
}
challenge := strings.Split(plain, ":")[1]
if len(challenge) > 32 {
c.Respond("Invalid server challenge in '.obj.cipher' - Maximum of 32 characters")
return
}
// Define response builder for serverhello packet
cipher := "serverhello:" + challenge
if !envDisableCrypt {
cipherBuf, err := c.Crypt.Encrypt([]byte(cipher))
if err != nil {
c.Log.Error("failed to encrypt serverhello challenge response", zap.Error(err))
c.Respond(statusInternalServerError)
return
}
cipher = base64.RawStdEncoding.EncodeToString(cipherBuf)
}
c.MgmtWrite(xhelloPacket{
Type: "serverhello",
Obj: xhelloObj{
Cipher: &cipher,
},
})
c.ClienthelloDone = true
// Connection verified -> enable complete encryption and send initial pc
c.Log = c.Log.With(zap.Int("user_id", c.UserID))
c.Log.Info("authenticated")
c.IsEncrypted = true
c.Pc = rand.Uint32() / 2
c.StartPc = c.Pc
c.CurType = "initialpc"
c.RespondNil()
}