validator.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package vmess
  2. import (
  3. "crypto/hmac"
  4. "crypto/sha256"
  5. "hash/crc64"
  6. "strings"
  7. "sync"
  8. "github.com/xtls/xray-core/common/dice"
  9. "github.com/xtls/xray-core/common/protocol"
  10. "github.com/xtls/xray-core/proxy/vmess/aead"
  11. )
  12. // TimedUserValidator is a user Validator based on time.
  13. type TimedUserValidator struct {
  14. sync.RWMutex
  15. users []*protocol.MemoryUser
  16. behaviorSeed uint64
  17. behaviorFused bool
  18. aeadDecoderHolder *aead.AuthIDDecoderHolder
  19. }
  20. // NewTimedUserValidator creates a new TimedUserValidator.
  21. func NewTimedUserValidator() *TimedUserValidator {
  22. tuv := &TimedUserValidator{
  23. users: make([]*protocol.MemoryUser, 0, 16),
  24. aeadDecoderHolder: aead.NewAuthIDDecoderHolder(),
  25. }
  26. return tuv
  27. }
  28. func (v *TimedUserValidator) Add(u *protocol.MemoryUser) error {
  29. v.Lock()
  30. defer v.Unlock()
  31. v.users = append(v.users, u)
  32. account := u.Account.(*MemoryAccount)
  33. if !v.behaviorFused {
  34. hashkdf := hmac.New(sha256.New, []byte("VMESSBSKDF"))
  35. hashkdf.Write(account.ID.Bytes())
  36. v.behaviorSeed = crc64.Update(v.behaviorSeed, crc64.MakeTable(crc64.ECMA), hashkdf.Sum(nil))
  37. }
  38. var cmdkeyfl [16]byte
  39. copy(cmdkeyfl[:], account.ID.CmdKey())
  40. v.aeadDecoderHolder.AddUser(cmdkeyfl, u)
  41. return nil
  42. }
  43. func (v *TimedUserValidator) GetAEAD(userHash []byte) (*protocol.MemoryUser, bool, error) {
  44. v.RLock()
  45. defer v.RUnlock()
  46. var userHashFL [16]byte
  47. copy(userHashFL[:], userHash)
  48. userd, err := v.aeadDecoderHolder.Match(userHashFL)
  49. if err != nil {
  50. return nil, false, err
  51. }
  52. return userd.(*protocol.MemoryUser), true, err
  53. }
  54. func (v *TimedUserValidator) Remove(email string) bool {
  55. v.Lock()
  56. defer v.Unlock()
  57. email = strings.ToLower(email)
  58. idx := -1
  59. for i, u := range v.users {
  60. if strings.EqualFold(u.Email, email) {
  61. idx = i
  62. var cmdkeyfl [16]byte
  63. copy(cmdkeyfl[:], u.Account.(*MemoryAccount).ID.CmdKey())
  64. v.aeadDecoderHolder.RemoveUser(cmdkeyfl)
  65. break
  66. }
  67. }
  68. if idx == -1 {
  69. return false
  70. }
  71. ulen := len(v.users)
  72. v.users[idx] = v.users[ulen-1]
  73. v.users[ulen-1] = nil
  74. v.users = v.users[:ulen-1]
  75. return true
  76. }
  77. func (v *TimedUserValidator) GetBehaviorSeed() uint64 {
  78. v.Lock()
  79. defer v.Unlock()
  80. v.behaviorFused = true
  81. if v.behaviorSeed == 0 {
  82. v.behaviorSeed = dice.RollUint64()
  83. }
  84. return v.behaviorSeed
  85. }
  86. var ErrNotFound = newError("Not Found")
  87. var ErrTainted = newError("ErrTainted")