authentication.go 2.8 KB

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