validator.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package shadowsocks
  2. import (
  3. "crypto/cipher"
  4. "crypto/hmac"
  5. "crypto/sha256"
  6. "hash/crc64"
  7. "strings"
  8. "sync"
  9. "github.com/xtls/xray-core/common/dice"
  10. "github.com/xtls/xray-core/common/protocol"
  11. )
  12. // Validator stores valid Shadowsocks users.
  13. type Validator struct {
  14. sync.RWMutex
  15. users []*protocol.MemoryUser
  16. behaviorSeed uint64
  17. behaviorFused bool
  18. }
  19. var ErrNotFound = newError("Not Found")
  20. // Add a Shadowsocks user.
  21. func (v *Validator) Add(u *protocol.MemoryUser) error {
  22. v.Lock()
  23. defer v.Unlock()
  24. account := u.Account.(*MemoryAccount)
  25. if !account.Cipher.IsAEAD() && len(v.users) > 0 {
  26. return newError("The cipher is not support Single-port Multi-user")
  27. }
  28. v.users = append(v.users, u)
  29. if !v.behaviorFused {
  30. hashkdf := hmac.New(sha256.New, []byte("SSBSKDF"))
  31. hashkdf.Write(account.Key)
  32. v.behaviorSeed = crc64.Update(v.behaviorSeed, crc64.MakeTable(crc64.ECMA), hashkdf.Sum(nil))
  33. }
  34. return nil
  35. }
  36. // Del a Shadowsocks user with a non-empty Email.
  37. func (v *Validator) Del(email string) error {
  38. if email == "" {
  39. return newError("Email must not be empty.")
  40. }
  41. v.Lock()
  42. defer v.Unlock()
  43. email = strings.ToLower(email)
  44. idx := -1
  45. for i, u := range v.users {
  46. if strings.EqualFold(u.Email, email) {
  47. idx = i
  48. break
  49. }
  50. }
  51. if idx == -1 {
  52. return newError("User ", email, " not found.")
  53. }
  54. ulen := len(v.users)
  55. v.users[idx] = v.users[ulen-1]
  56. v.users[ulen-1] = nil
  57. v.users = v.users[:ulen-1]
  58. return nil
  59. }
  60. // Get a Shadowsocks user.
  61. func (v *Validator) Get(bs []byte, command protocol.RequestCommand) (u *protocol.MemoryUser, aead cipher.AEAD, ret []byte, ivLen int32, err error) {
  62. v.RLock()
  63. defer v.RUnlock()
  64. for _, user := range v.users {
  65. if account := user.Account.(*MemoryAccount); account.Cipher.IsAEAD() {
  66. // AEAD payload decoding requires the payload to be over 32 bytes
  67. if len(bs) < 32 {
  68. continue
  69. }
  70. aeadCipher := account.Cipher.(*AEADCipher)
  71. ivLen = aeadCipher.IVSize()
  72. iv := bs[:ivLen]
  73. subkey := make([]byte, 32)
  74. subkey = subkey[:aeadCipher.KeyBytes]
  75. hkdfSHA1(account.Key, iv, subkey)
  76. aead = aeadCipher.AEADAuthCreator(subkey)
  77. var matchErr error
  78. switch command {
  79. case protocol.RequestCommandTCP:
  80. data := make([]byte, 4+aead.NonceSize())
  81. ret, matchErr = aead.Open(data[:0], data[4:], bs[ivLen:ivLen+18], nil)
  82. case protocol.RequestCommandUDP:
  83. data := make([]byte, 8192)
  84. ret, matchErr = aead.Open(data[:0], data[8192-aead.NonceSize():8192], bs[ivLen:], nil)
  85. }
  86. if matchErr == nil {
  87. u = user
  88. err = account.CheckIV(iv)
  89. return
  90. }
  91. } else {
  92. u = user
  93. ivLen = user.Account.(*MemoryAccount).Cipher.IVSize()
  94. // err = user.Account.(*MemoryAccount).CheckIV(bs[:ivLen]) // The IV size of None Cipher is 0.
  95. return
  96. }
  97. }
  98. return nil, nil, nil, 0, ErrNotFound
  99. }
  100. func (v *Validator) GetBehaviorSeed() uint64 {
  101. v.Lock()
  102. defer v.Unlock()
  103. v.behaviorFused = true
  104. if v.behaviorSeed == 0 {
  105. v.behaviorSeed = dice.RollUint64()
  106. }
  107. return v.behaviorSeed
  108. }