github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/proxy/vmess/validator.go (about)

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