authentication.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package binlog
  2. import (
  3. "bytes"
  4. "crypto/sha1"
  5. "crypto/sha256"
  6. )
  7. type AuthResponsePacket struct {
  8. PacketLength uint64
  9. SequenceID uint64
  10. Status uint64
  11. PluginName string
  12. AuthPluginData *bytes.Buffer
  13. }
  14. func (c *Conn) decodeAuthResponsePacket() (*AuthResponsePacket, error) {
  15. packet := AuthResponsePacket{}
  16. packet.PacketLength = c.getInt(TypeFixedInt, 3)
  17. packet.SequenceID = c.getInt(TypeFixedInt, 1)
  18. packet.Status = c.getInt(TypeFixedInt, 1)
  19. packet.PluginName = c.getString(TypeNullTerminatedString, 0)
  20. packet.AuthPluginData = c.readBytes(20)
  21. err := c.scanner.Err()
  22. if err != nil {
  23. return nil, err
  24. }
  25. return &packet, err
  26. }
  27. func (c *Conn) writeAuthSwitchPacket(ap *AuthResponsePacket) error {
  28. salt := ap.AuthPluginData.Bytes()
  29. password := []byte(c.HandshakeResponse.AuthResponse)
  30. c.authenticate(salt, password)
  31. if c.Flush() != nil {
  32. return c.Flush()
  33. }
  34. return nil
  35. }
  36. func (c *Conn) authenticate(salt []byte, password []byte) {
  37. var ar []byte
  38. salt = salt[:20] // trim null byte from end.
  39. switch c.Handshake.AuthPluginName {
  40. case "mysql_native_password":
  41. ar = c.nativeSha1Auth(salt, password)
  42. case "caching_sha2_password":
  43. ar = c.cachingSha2Auth(salt, password)
  44. }
  45. hr := c.HandshakeResponse
  46. hr.AuthResponseLength = uint64(len(ar))
  47. if hr.ClientFlag.PluginAuthLenEncClientData {
  48. c.putInt(TypeLenEncInt, hr.AuthResponseLength, 0)
  49. c.putBytes(ar)
  50. } else if hr.ClientFlag.SecureConnection {
  51. c.putInt(TypeFixedInt, hr.AuthResponseLength, 1)
  52. c.putBytes(ar)
  53. } else {
  54. c.putString(TypeNullTerminatedString, string(ar))
  55. }
  56. }
  57. func (c *Conn) nativeSha1Auth(salt []byte, password []byte) []byte {
  58. if len(password) < 1 {
  59. return nil
  60. }
  61. pHash := c.sha1Hash(password)
  62. pHashHash := c.sha1Hash(pHash)
  63. spHash := c.sha1Hash(append(salt, pHashHash...))
  64. for i := range pHash {
  65. pHash[i] ^= spHash[i]
  66. }
  67. return pHash
  68. }
  69. func (c *Conn) cachingSha2Auth(salt []byte, password []byte) []byte {
  70. if len(password) < 1 {
  71. return nil
  72. }
  73. pHash := c.sha256Hash(password)
  74. pHashHash := c.sha256Hash(pHash)
  75. pHashHashHash := c.sha256Hash(pHashHash)
  76. authData := c.sha256Hash(append(pHashHashHash, salt...))
  77. for i := range pHash {
  78. pHash[i] ^= authData[i]
  79. }
  80. return pHash
  81. }
  82. func (c *Conn) sha1Hash(word []byte) []byte {
  83. s := sha1.New()
  84. s.Write(word)
  85. return s.Sum(nil)
  86. }
  87. func (c *Conn) sha256Hash(word []byte) []byte {
  88. s := sha256.New()
  89. s.Write(word)
  90. return s.Sum(nil)
  91. }