This repository has been archived by the owner on Feb 22, 2023. It is now read-only.
forked from go-mysql-org/go-mysql
/
auth.go
119 lines (84 loc) · 2.51 KB
/
auth.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
package server
import (
"bytes"
"encoding/binary"
. "github.com/siddontang/go-mysql/mysql"
)
func (c *Conn) writeInitialHandshake() error {
capability := CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG |
CLIENT_CONNECT_WITH_DB | CLIENT_PROTOCOL_41 |
CLIENT_TRANSACTIONS | CLIENT_SECURE_CONNECTION
data := make([]byte, 4, 128)
//min version 10
data = append(data, 10)
//server version[00]
data = append(data, ServerVersion...)
data = append(data, 0)
//connection id
data = append(data, byte(c.connectionID), byte(c.connectionID>>8), byte(c.connectionID>>16), byte(c.connectionID>>24))
//auth-plugin-data-part-1
data = append(data, c.salt[0:8]...)
//filter [00]
data = append(data, 0)
//capability flag lower 2 bytes, using default capability here
data = append(data, byte(capability), byte(capability>>8))
//charset, utf-8 default
data = append(data, uint8(DEFAULT_COLLATION_ID))
//status
data = append(data, byte(c.status), byte(c.status>>8))
//below 13 byte may not be used
//capability flag upper 2 bytes, using default capability here
data = append(data, byte(capability>>16), byte(capability>>24))
//filter [0x15], for wireshark dump, value is 0x15
data = append(data, 0x15)
//reserved 10 [00]
data = append(data, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
//auth-plugin-data-part-2
data = append(data, c.salt[8:]...)
//filter [00]
data = append(data, 0)
return c.WritePacket(data)
}
func (c *Conn) readHandshakeResponse(password string) error {
data, err := c.ReadPacket()
if err != nil {
return err
}
pos := 0
//capability
c.capability = binary.LittleEndian.Uint32(data[:4])
pos += 4
//skip max packet size
pos += 4
//charset, skip, if you want to use another charset, use set names
//c.collation = CollationId(data[pos])
pos++
//skip reserved 23[00]
pos += 23
//user name
user := string(data[pos : pos+bytes.IndexByte(data[pos:], 0)])
pos += len(user) + 1
if c.user != user {
return NewDefaultError(ER_NO_SUCH_USER, user, c.RemoteAddr().String())
}
//auth length and auth
authLen := int(data[pos])
pos++
auth := data[pos : pos+authLen]
checkAuth := CalcPassword(c.salt, []byte(password))
if !bytes.Equal(auth, checkAuth) {
return NewDefaultError(ER_ACCESS_DENIED_ERROR, c.RemoteAddr().String(), c.user, "Yes")
}
pos += authLen
if c.capability|CLIENT_CONNECT_WITH_DB > 0 {
if len(data[pos:]) == 0 {
return nil
}
db := string(data[pos : pos+bytes.IndexByte(data[pos:], 0)])
pos += len(db) + 1
if err = c.h.UseDB(db); err != nil {
return err
}
}
return nil
}