github.com/EagleQL/Xray-core@v1.4.3/proxy/shadowsocks/validator.go (about) 1 package shadowsocks 2 3 import ( 4 "crypto/cipher" 5 "strings" 6 "sync" 7 8 "github.com/xtls/xray-core/common/protocol" 9 ) 10 11 // Validator stores valid Shadowsocks users. 12 type Validator struct { 13 // Considering email's usage here, map + sync.Mutex/RWMutex may have better performance. 14 email sync.Map 15 users sync.Map 16 } 17 18 // Add a Shadowsocks user, Email must be empty or unique. 19 func (v *Validator) Add(u *protocol.MemoryUser) error { 20 account := u.Account.(*MemoryAccount) 21 22 if !account.Cipher.IsAEAD() && v.Count() > 0 { 23 return newError("The cipher do not support Single-port Multi-user") 24 } 25 26 if u.Email != "" { 27 _, loaded := v.email.LoadOrStore(strings.ToLower(u.Email), u) 28 if loaded { 29 return newError("User ", u.Email, " already exists.") 30 } 31 } 32 33 v.users.Store(string(account.Key)+"&"+account.GetCipherName(), u) 34 return nil 35 } 36 37 // Del a Shadowsocks user with a non-empty Email. 38 func (v *Validator) Del(e string) error { 39 if e == "" { 40 return newError("Email must not be empty.") 41 } 42 le := strings.ToLower(e) 43 u, _ := v.email.Load(le) 44 if u == nil { 45 return newError("User ", e, " not found.") 46 } 47 account := u.(*protocol.MemoryUser).Account.(*MemoryAccount) 48 v.email.Delete(le) 49 v.users.Delete(string(account.Key) + "&" + account.GetCipherName()) 50 return nil 51 } 52 53 // Count the number of Shadowsocks users 54 func (v *Validator) Count() int { 55 length := 0 56 v.users.Range(func(_, _ interface{}) bool { 57 length++ 58 59 return true 60 }) 61 return length 62 } 63 64 // Get a Shadowsocks user and the user's cipher. 65 func (v *Validator) Get(bs []byte, command protocol.RequestCommand) (u *protocol.MemoryUser, aead cipher.AEAD, ret []byte, ivLen int32, err error) { 66 var dataSize int 67 68 switch command { 69 case protocol.RequestCommandTCP: 70 dataSize = 16 71 case protocol.RequestCommandUDP: 72 dataSize = 8192 73 } 74 75 var aeadCipher *AEADCipher 76 subkey := make([]byte, 32) 77 data := make([]byte, dataSize) 78 79 v.users.Range(func(key, user interface{}) bool { 80 account := user.(*protocol.MemoryUser).Account.(*MemoryAccount) 81 aeadCipher = account.Cipher.(*AEADCipher) 82 ivLen = aeadCipher.IVSize() 83 subkey = subkey[:aeadCipher.KeyBytes] 84 hkdfSHA1(account.Key, bs[:ivLen], subkey) 85 aead = aeadCipher.AEADAuthCreator(subkey) 86 87 switch command { 88 case protocol.RequestCommandTCP: 89 ret, err = aead.Open(data[:0], data[4:16], bs[ivLen:ivLen+18], nil) 90 case protocol.RequestCommandUDP: 91 ret, err = aead.Open(data[:0], data[8180:8192], bs[ivLen:], nil) 92 } 93 94 if err == nil { 95 u = user.(*protocol.MemoryUser) 96 return false 97 } 98 return true 99 }) 100 101 return 102 } 103 104 // Get the only user without authentication 105 func (v *Validator) GetOnlyUser() (u *protocol.MemoryUser, ivLen int32) { 106 v.users.Range(func(_, user interface{}) bool { 107 u = user.(*protocol.MemoryUser) 108 return false 109 }) 110 ivLen = u.Account.(*MemoryAccount).Cipher.IVSize() 111 112 return 113 }