4 "github.com/HimbeerserverDE/srp"
5 "github.com/Shopify/go-lua"
6 "github.com/anon55555/mt"
14 asInit authState = iota
28 srpBytesA, bytesA []byte
31 func getAuth(l *lua.State) *Auth {
32 return lua.CheckUserData(l, 1, "hydra.auth").(*Auth)
35 func (auth *Auth) create(client *Client) {
37 auth.language = "en_US"
41 func (auth *Auth) push(l *lua.State) {
44 if lua.NewMetaTable(l, "hydra.auth") {
45 lua.NewLibrary(l, []lua.RegistryFunction{
46 {Name: "username", Function: l_auth_username},
47 {Name: "password", Function: l_auth_password},
48 {Name: "language", Function: l_auth_language},
49 {Name: "state", Function: l_auth_state},
51 l.SetField(-2, "__index")
56 func (auth *Auth) canConnect() (bool, string) {
57 if auth.username == "" {
58 return false, "missing username"
64 func (auth *Auth) connect() {
66 for auth.state == asInit && auth.client.state == csConnected {
67 auth.client.conn.SendCmd(&mt.ToSrvInit{
71 PlayerName: auth.username,
73 time.Sleep(500 * time.Millisecond)
78 func (auth *Auth) setError(err string) {
81 auth.client.conn.Close()
84 func (auth *Auth) checkState(state authState, pkt *mt.Pkt) bool {
85 if auth.state == state {
89 auth.setError("received " + pktToString(pkt) + " in invalid state")
93 func (auth *Auth) handle(pkt *mt.Pkt, l *lua.State, idx int) {
98 switch cmd := pkt.Cmd.(type) {
100 if !auth.checkState(asInit, pkt) {
104 if cmd.SerializeVer != 28 {
105 auth.setError("unsupported serialize_ver")
109 if cmd.AuthMethods == mt.FirstSRP {
110 salt, verifier, err := srp.NewClient([]byte(strings.ToLower(auth.username)), []byte(auth.password))
112 auth.setError(err.Error())
116 auth.client.conn.SendCmd(&mt.ToSrvFirstSRP{
119 EmptyPasswd: auth.password == "",
121 auth.state = asVerified
122 } else if cmd.AuthMethods == mt.SRP {
124 auth.srpBytesA, auth.bytesA, err = srp.InitiateHandshake()
126 auth.setError(err.Error())
130 auth.client.conn.SendCmd(&mt.ToSrvSRPBytesA{
134 auth.state = asRequested
136 auth.setError("invalid auth methods")
140 case *mt.ToCltSRPBytesSaltB:
141 if !auth.checkState(asRequested, pkt) {
145 srpBytesK, err := srp.CompleteHandshake(auth.srpBytesA, auth.bytesA, []byte(strings.ToLower(auth.username)), []byte(auth.password), cmd.Salt, cmd.B)
147 auth.setError(err.Error())
151 M := srp.ClientProof([]byte(auth.username), cmd.Salt, auth.srpBytesA, cmd.B, srpBytesK)
152 auth.srpBytesA = []byte{}
153 auth.bytesA = []byte{}
156 auth.setError("srp safety check fail")
160 auth.client.conn.SendCmd(&mt.ToSrvSRPBytesM{
163 auth.state = asVerified
165 case *mt.ToCltAcceptAuth:
166 auth.client.conn.SendCmd(&mt.ToSrvInit2{Lang: auth.language})
168 case *mt.ToCltTimeOfDay:
169 if auth.state == asActive {
173 if !auth.checkState(asVerified, pkt) {
177 auth.client.conn.SendCmd(&mt.ToSrvCltReady{
183 // Version: "hydra-dragonfire",
186 auth.state = asActive
190 func l_auth_username(l *lua.State) int {
194 if auth.client.state > csNew {
195 panic("can't change username after connecting")
197 auth.username = lua.CheckString(l, 2)
200 l.PushString(auth.username)
205 func l_auth_password(l *lua.State) int {
209 if auth.client.state > csNew {
210 panic("can't change password after connecting")
212 auth.password = lua.CheckString(l, 2)
215 l.PushString(auth.password)
220 func l_auth_language(l *lua.State) int {
224 if auth.client.state > csNew {
225 panic("can't change language after connecting")
227 auth.language = lua.CheckString(l, 2)
230 l.PushString(auth.language)
235 func l_auth_state(l *lua.State) int {
242 l.PushString("requested")
244 l.PushString("verified")
246 l.PushString("active")
248 l.PushString("error")
249 l.PushString(auth.err)