123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- package vmess
- import (
- "crypto/hmac"
- "crypto/sha256"
- "hash/crc64"
- "strings"
- "sync"
- "github.com/xtls/xray-core/common/dice"
- "github.com/xtls/xray-core/common/errors"
- "github.com/xtls/xray-core/common/protocol"
- "github.com/xtls/xray-core/proxy/vmess/aead"
- )
- // TimedUserValidator is a user Validator based on time.
- type TimedUserValidator struct {
- sync.RWMutex
- users []*protocol.MemoryUser
- behaviorSeed uint64
- behaviorFused bool
- aeadDecoderHolder *aead.AuthIDDecoderHolder
- }
- // NewTimedUserValidator creates a new TimedUserValidator.
- func NewTimedUserValidator() *TimedUserValidator {
- tuv := &TimedUserValidator{
- users: make([]*protocol.MemoryUser, 0, 16),
- aeadDecoderHolder: aead.NewAuthIDDecoderHolder(),
- }
- return tuv
- }
- func (v *TimedUserValidator) Add(u *protocol.MemoryUser) error {
- v.Lock()
- defer v.Unlock()
- v.users = append(v.users, u)
- account, ok := u.Account.(*MemoryAccount)
- if !ok {
- return errors.New("account type is incorrect")
- }
- if !v.behaviorFused {
- hashkdf := hmac.New(sha256.New, []byte("VMESSBSKDF"))
- hashkdf.Write(account.ID.Bytes())
- v.behaviorSeed = crc64.Update(v.behaviorSeed, crc64.MakeTable(crc64.ECMA), hashkdf.Sum(nil))
- }
- var cmdkeyfl [16]byte
- copy(cmdkeyfl[:], account.ID.CmdKey())
- v.aeadDecoderHolder.AddUser(cmdkeyfl, u)
- return nil
- }
- func (v *TimedUserValidator) GetUsers() []*protocol.MemoryUser {
- v.Lock()
- defer v.Unlock()
- dst := make([]*protocol.MemoryUser, len(v.users))
- copy(dst, v.users)
- return dst
- }
- func (v *TimedUserValidator) GetCount() int64 {
- v.Lock()
- defer v.Unlock()
- return int64(len(v.users))
- }
- func (v *TimedUserValidator) GetAEAD(userHash []byte) (*protocol.MemoryUser, bool, error) {
- v.RLock()
- defer v.RUnlock()
- var userHashFL [16]byte
- copy(userHashFL[:], userHash)
- userd, err := v.aeadDecoderHolder.Match(userHashFL)
- if err != nil {
- return nil, false, err
- }
- return userd.(*protocol.MemoryUser), true, nil
- }
- func (v *TimedUserValidator) Remove(email string) bool {
- v.Lock()
- defer v.Unlock()
- email = strings.ToLower(email)
- idx := -1
- for i, u := range v.users {
- if strings.EqualFold(u.Email, email) {
- idx = i
- var cmdkeyfl [16]byte
- copy(cmdkeyfl[:], u.Account.(*MemoryAccount).ID.CmdKey())
- v.aeadDecoderHolder.RemoveUser(cmdkeyfl)
- break
- }
- }
- if idx == -1 {
- return false
- }
- ulen := len(v.users)
- v.users[idx] = v.users[ulen-1]
- v.users[ulen-1] = nil
- v.users = v.users[:ulen-1]
- return true
- }
- func (v *TimedUserValidator) GetBehaviorSeed() uint64 {
- v.Lock()
- defer v.Unlock()
- v.behaviorFused = true
- if v.behaviorSeed == 0 {
- v.behaviorSeed = dice.RollUint64()
- }
- return v.behaviorSeed
- }
- var ErrNotFound = errors.New("Not Found")
- var ErrTainted = errors.New("ErrTainted")
|