validator.go 2.3 KB

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