handshake.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. package binlog
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. )
  6. type Capabilities struct {
  7. LongPassword bool
  8. FoundRows bool
  9. LongFlag bool
  10. ConnectWithDB bool
  11. NoSchema bool
  12. Compress bool
  13. ODBC bool
  14. LocalFiles bool
  15. IgnoreSpace bool
  16. Protocol41 bool
  17. Interactive bool
  18. SSL bool
  19. IgnoreSigpipe bool
  20. Transactions bool
  21. LegacyProtocol41 bool
  22. SecureConnection bool
  23. MultiStatements bool
  24. MultiResults bool
  25. PSMultiResults bool
  26. PluginAuth bool
  27. ConnectAttrs bool
  28. PluginAuthLenEncClientData bool
  29. CanHandleExpiredPasswords bool
  30. SessionTrack bool
  31. DeprecateEOF bool
  32. SSLVerifyServerCert bool
  33. OptionalResultSetMetadata bool
  34. RememberOptions bool
  35. }
  36. type Status struct {
  37. InTrans bool
  38. Autocommit bool
  39. MoreResultsExists bool
  40. QueryNoGoodIndexUsed bool
  41. QueryNoIndexUsed bool
  42. CursorExists bool
  43. LastRowSent bool
  44. DBDropped bool
  45. NoBackslashEscapes bool
  46. MetadataChanged bool
  47. QueryWasSlow bool
  48. PSOutParams bool
  49. InTransReadonly bool
  50. SessionStateChanged bool
  51. }
  52. type Handshake struct {
  53. PacketLength uint64
  54. SequenceID uint64
  55. ProtocolVersion uint64
  56. ServerVersion string
  57. ThreadID uint64
  58. AuthPluginDataPart1 []byte
  59. CapabilityFlags1 []byte
  60. Charset uint64
  61. StatusFlags []byte
  62. CapabilityFlags2 []byte
  63. AuthPluginDataLength uint64
  64. AuthPluginDataPart2 []byte
  65. AuthPluginName string
  66. Capabilities *Capabilities
  67. Status *Status
  68. }
  69. type HandshakeResponse struct {
  70. ClientFlag *Capabilities
  71. MaxPacketSize uint64
  72. CharacterSet uint64
  73. Username string
  74. AuthResponseLength uint64
  75. AuthResponse string
  76. Database string
  77. ClientPluginName string
  78. KeyValues map[string]string
  79. }
  80. func (c *Conn) decodeCapabilityFlags(hs *Handshake) {
  81. var cfb = append(hs.CapabilityFlags1, hs.CapabilityFlags2...)
  82. capabilities := c.bitmaskToStruct(cfb, hs.Capabilities).(Capabilities)
  83. hs.Capabilities = &capabilities
  84. }
  85. func (c *Conn) decodeStatusFlags(hs *Handshake) {
  86. status := c.bitmaskToStruct(hs.StatusFlags, hs.Status).(Status)
  87. hs.Status = &status
  88. }
  89. func (c *Conn) decodeHandshakePacket() error {
  90. packet := Handshake{}
  91. var err error
  92. packet.PacketLength, err = c.getInt(TypeFixedInt, 3)
  93. if err != nil {
  94. return err
  95. }
  96. packet.SequenceID, err = c.getInt(TypeFixedInt, 1)
  97. if err != nil {
  98. return err
  99. }
  100. packet.ProtocolVersion, err = c.getInt(TypeFixedInt, 1)
  101. if err != nil {
  102. return err
  103. }
  104. packet.ServerVersion, err = c.getString(TypeNullTerminatedString, 0)
  105. if err != nil {
  106. return err
  107. }
  108. packet.ThreadID, err = c.getInt(TypeFixedInt, 4)
  109. if err != nil {
  110. return err
  111. }
  112. packet.AuthPluginDataPart1, err = c.getBytes(8)
  113. if err != nil {
  114. return err
  115. }
  116. err = c.consumeBytes(1)
  117. if err != nil {
  118. return err
  119. }
  120. packet.CapabilityFlags1, err = c.getBytes(2)
  121. if err != nil {
  122. return err
  123. }
  124. packet.Charset, err = c.getInt(TypeFixedInt, 1)
  125. if err != nil {
  126. return err
  127. }
  128. packet.StatusFlags, err = c.getBytes(2)
  129. if err != nil {
  130. return err
  131. }
  132. c.decodeStatusFlags(&packet)
  133. packet.CapabilityFlags2, err = c.getBytes(2)
  134. if err != nil {
  135. return err
  136. }
  137. c.decodeCapabilityFlags(&packet)
  138. packet.AuthPluginDataLength, err = c.getInt(TypeFixedInt, 1)
  139. if err != nil {
  140. return err
  141. }
  142. err = c.consumeBytes(10)
  143. if err != nil {
  144. return err
  145. }
  146. packet.AuthPluginDataPart2, err = c.getBytes(packet.AuthPluginDataLength - 8)
  147. if err != nil {
  148. return err
  149. }
  150. packet.AuthPluginName, err = c.getString(TypeNullTerminatedString, 0)
  151. if err != nil {
  152. return err
  153. }
  154. c.Handshake = &packet
  155. return nil
  156. }
  157. func (c *Conn) encodeHandshakeResponse() []byte {
  158. hr := NewHandshakeResponse()
  159. buf := bytes.NewBuffer(make([]byte, 0))
  160. // Capabilities flag.
  161. //var cf capability = 0
  162. // Write Capability Flags.
  163. //buf.Write([]byte(cf))
  164. // Write MaxPacketSize
  165. //buf.Write()
  166. // Write CharacterSet
  167. cs := make([]byte, 2)
  168. binary.LittleEndian.PutUint16(cs, uint16(hr.CharacterSet))
  169. buf.Write(cs[:1])
  170. // Write Filler
  171. buf.Write(make([]byte, 23))
  172. // Write username
  173. u := append([]byte(hr.Username), NullByte)
  174. buf.Write(u)
  175. salt := append(c.Handshake.AuthPluginDataPart1, c.Handshake.AuthPluginDataPart2...)
  176. ar := c.cachingSha2Auth(salt, []byte(hr.AuthResponse))
  177. if hr.ClientFlag.PluginAuthLenEncClientData {
  178. buf.Write(c.encLenEncInt(uint64(len(ar))))
  179. buf.Write(ar)
  180. } else if hr.ClientFlag.SecureConnection {
  181. l := make([]byte, 2)
  182. binary.LittleEndian.PutUint16(l, uint16(len(ar)))
  183. buf.Write(l[:1])
  184. buf.Write(ar)
  185. } else {
  186. buf.Write(append(ar, NullByte))
  187. }
  188. // Write database name
  189. if hr.ClientFlag.ConnectWithDB {
  190. buf.Write(append([]byte(hr.Database), NullByte))
  191. }
  192. // Write auth plugin
  193. if hr.ClientFlag.PluginAuth {
  194. buf.Write([]byte(hr.ClientPluginName))
  195. }
  196. pl := make([]byte, 4)
  197. binary.LittleEndian.PutUint32(pl, uint32(buf.Len()))
  198. p := append(pl[:3], 1)
  199. p = append(p, buf.Bytes()...)
  200. buf = bytes.NewBuffer(p)
  201. return buf.Bytes()
  202. }
  203. func NewHandshakeResponse() *HandshakeResponse {
  204. return &HandshakeResponse{
  205. ClientFlag: &Capabilities{
  206. LongPassword: true,
  207. FoundRows: true,
  208. LongFlag: true,
  209. ConnectWithDB: true,
  210. NoSchema: false,
  211. Compress: false,
  212. ODBC: false,
  213. LocalFiles: false,
  214. IgnoreSpace: true,
  215. Protocol41: true,
  216. Interactive: true,
  217. SSL: false,
  218. IgnoreSigpipe: false,
  219. Transactions: true,
  220. LegacyProtocol41: false,
  221. SecureConnection: true,
  222. MultiStatements: false,
  223. MultiResults: false,
  224. PSMultiResults: true,
  225. PluginAuth: false,
  226. ConnectAttrs: false,
  227. PluginAuthLenEncClientData: false,
  228. CanHandleExpiredPasswords: false,
  229. SessionTrack: true,
  230. DeprecateEOF: true,
  231. SSLVerifyServerCert: false,
  232. OptionalResultSetMetadata: true,
  233. RememberOptions: true,
  234. },
  235. MaxPacketSize: MaxPacketSize,
  236. CharacterSet: 45,
  237. Username: "",
  238. AuthResponseLength: 0,
  239. AuthResponse: "",
  240. Database: "",
  241. ClientPluginName: "",
  242. KeyValues: nil,
  243. }
  244. }