validator.go 3.0 KB

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