-
-
Notifications
You must be signed in to change notification settings - Fork 382
/
handshakeResponseOkPacket.go
142 lines (124 loc) · 3.9 KB
/
handshakeResponseOkPacket.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package mysql
import (
"bytes"
"encoding/base64"
"fmt"
"go.keploy.io/server/v2/pkg/models"
)
type HandshakeResponseOk struct {
PacketIndicator string `json:"packet_indicator,omitempty" yaml:"packet_indicator,omitempty,flow"`
PluginDetails PluginDetails `json:"plugin_details,omitempty" yaml:"plugin_details,omitempty,flow"`
RemainingBytes string `json:"remaining_bytes,omitempty" yaml:"remaining_bytes,omitempty,flow"`
}
func decodeHandshakeResponseOk(data []byte) (*HandshakeResponseOk, error) {
var (
packetIndicator string
authType string
message string
remainingBytes []byte
)
if isPluginData {
publicKeyData := string(data[1:])
authType = "PublicKeyAuthentication"
message = "Public key for authentication"
remainingBytes = []byte(publicKeyData)
}
switch data[0] {
case models.OK:
packetIndicator = "OK"
case models.AuthMoreData:
packetIndicator = "AuthMoreData"
case models.EOF:
packetIndicator = "EOF"
default:
packetIndicator = "Unknown"
}
if data[0] == models.AuthMoreData {
count := int(data[0])
var authData = data[1 : count+1]
switch handshakePluginName {
case "caching_sha2_password":
switch len(authData) {
case 1:
switch authData[0] {
case models.CachingSha2PasswordFastAuthSuccess:
authType = "cachingSha2PasswordFastAuthSuccess"
message = "Ok"
remainingBytes = data[count+1:]
case models.CachingSha2PasswordPerformFullAuthentication:
authType = "cachingSha2PasswordPerformFullAuthentication"
message = ""
remainingBytes = data[count+1:]
}
}
}
}
return &HandshakeResponseOk{
PacketIndicator: packetIndicator,
PluginDetails: PluginDetails{
Type: authType,
Message: message,
},
RemainingBytes: base64.StdEncoding.EncodeToString(remainingBytes),
}, nil
}
func encodeHandshakeResponseOk(packet *models.MySQLHandshakeResponseOk) ([]byte, error) {
var buf bytes.Buffer
var payload []byte
RemainingBytesValue, _ := base64.StdEncoding.DecodeString(packet.RemainingBytes)
if packet.PluginDetails.Type == "PublicKeyAuthentication" {
publicKeydata := []byte(RemainingBytesValue)
// Calculate the payload length
payloadLength := len(publicKeydata) + 1 // +1 for the MySQL protocol version byte
// Construct the MySQL packet header
header := make([]byte, 4)
header[0] = byte(payloadLength & 0xFF) // Least significant byte
header[1] = byte((payloadLength >> 8) & 0xFF) // Middle byte
header[2] = byte((payloadLength >> 16) & 0xFF) // Most significant byte
header[3] = 4 // Sequence ID
// Append the MySQL protocol version byte and the public key data to the header
finalData := append(header, 0x01) // MySQL protocol version
finalData = append(finalData, publicKeydata...)
buf.Write(finalData)
payload = buf.Bytes()
} else {
var packetIndicator byte
switch packet.PacketIndicator {
case "OK":
packetIndicator = models.OK
case "AuthMoreData":
packetIndicator = models.AuthMoreData
case "EOF":
packetIndicator = models.EOF
default:
return nil, fmt.Errorf("unknown packet indicator")
}
buf.WriteByte(packetIndicator)
if packet.PacketIndicator == "AuthMoreData" {
var authData byte
switch packet.PluginDetails.Type {
case "cachingSha2PasswordFastAuthSuccess":
authData = models.CachingSha2PasswordFastAuthSuccess
case "cachingSha2PasswordPerformFullAuthentication":
authData = models.CachingSha2PasswordPerformFullAuthentication
default:
return nil, fmt.Errorf("unknown auth type")
}
// Write auth data
buf.WriteByte(authData)
}
// Write remaining bytes if available
if len(RemainingBytesValue) > 0 {
buf.Write(RemainingBytesValue)
}
// Create header
header := make([]byte, 4)
header[0] = 2 // sequence number
header[1] = 0
header[2] = 0
header[3] = 2
// Prepend header to the payload
payload = append(header, buf.Bytes()...)
}
return payload, nil
}