4 "github.com/HimbeerserverDE/srp"
5 "github.com/dragonfireclient/hydra-dragonfire/convert"
6 "github.com/dragonfireclient/mt"
7 "github.com/yuin/gopher-lua"
15 asInit authState = iota
22 type CompAuth struct {
30 srpBytesA, bytesA []byte
31 userdata *lua.LUserData
34 var compAuthFuncs = map[string]lua.LGFunction{
35 "username": l_comp_auth_username,
36 "password": l_comp_auth_password,
37 "language": l_comp_auth_language,
38 "version": l_comp_auth_version,
39 "state": l_comp_auth_state,
42 func getCompAuth(l *lua.LState) *CompAuth {
43 return l.CheckUserData(1).Value.(*CompAuth)
46 func (comp *CompAuth) create(client *Client, l *lua.LState) {
47 if client.state != csNew {
48 panic("can't add auth component after connect")
52 comp.language = "en_US"
53 comp.version = "hydra-dragonfire"
55 comp.userdata = l.NewUserData()
56 comp.userdata.Value = comp
57 l.SetMetatable(comp.userdata, l.GetTypeMetatable("hydra.comp.auth"))
60 func (comp *CompAuth) push() lua.LValue {
64 func (comp *CompAuth) connect() {
65 if comp.username == "" {
66 panic("missing username")
70 for comp.client.state == csConnected && comp.state == asInit {
71 comp.client.conn.SendCmd(&mt.ToSrvInit{
72 SerializeVer: serializeVer,
73 MinProtoVer: protoVer,
74 MaxProtoVer: protoVer,
75 PlayerName: comp.username,
77 time.Sleep(500 * time.Millisecond)
82 func (comp *CompAuth) fail(err string) {
85 comp.client.closeConn()
88 func (comp *CompAuth) checkState(state authState, pkt *mt.Pkt) bool {
89 if comp.state == state {
93 comp.fail("received " + string(convert.PushPktType(pkt)) + " in invalid state")
97 func (comp *CompAuth) process(pkt *mt.Pkt) {
98 if comp.state == asError {
102 switch cmd := pkt.Cmd.(type) {
104 if !comp.checkState(asInit, pkt) {
108 if cmd.SerializeVer != serializeVer {
109 comp.fail("unsupported serialize version")
113 if cmd.AuthMethods == mt.FirstSRP {
114 salt, verifier, err := srp.NewClient([]byte(strings.ToLower(comp.username)), []byte(comp.password))
116 comp.fail(err.Error())
120 comp.client.conn.SendCmd(&mt.ToSrvFirstSRP{
123 EmptyPasswd: comp.password == "",
125 comp.state = asVerified
126 } else if cmd.AuthMethods == mt.SRP {
128 comp.srpBytesA, comp.bytesA, err = srp.InitiateHandshake()
130 comp.fail(err.Error())
134 comp.client.conn.SendCmd(&mt.ToSrvSRPBytesA{
138 comp.state = asRequested
140 comp.fail("invalid auth methods")
144 case *mt.ToCltSRPBytesSaltB:
145 if !comp.checkState(asRequested, pkt) {
149 srpBytesK, err := srp.CompleteHandshake(comp.srpBytesA, comp.bytesA, []byte(strings.ToLower(comp.username)), []byte(comp.password), cmd.Salt, cmd.B)
151 comp.fail(err.Error())
155 M := srp.ClientProof([]byte(comp.username), cmd.Salt, comp.srpBytesA, cmd.B, srpBytesK)
156 comp.srpBytesA = []byte{}
157 comp.bytesA = []byte{}
160 comp.fail("srp safety check fail")
164 comp.client.conn.SendCmd(&mt.ToSrvSRPBytesM{
167 comp.state = asVerified
169 case *mt.ToCltAcceptAuth:
170 comp.client.conn.SendCmd(&mt.ToSrvInit2{Lang: comp.language})
172 case *mt.ToCltTimeOfDay:
173 if comp.state == asActive {
177 if !comp.checkState(asVerified, pkt) {
181 comp.client.conn.SendCmd(&mt.ToSrvCltReady{
187 Version: comp.version,
189 comp.state = asActive
193 func (comp *CompAuth) accessProperty(l *lua.LState, key string, ptr *string) int {
194 if str, ok := l.Get(2).(lua.LString); ok {
195 if comp.client.state != csNew {
196 panic("can't change " + key + " after connecting")
201 l.Push(lua.LString(*ptr))
206 func l_comp_auth_username(l *lua.LState) int {
207 comp := getCompAuth(l)
208 return comp.accessProperty(l, "username", &comp.username)
211 func l_comp_auth_password(l *lua.LState) int {
212 comp := getCompAuth(l)
213 return comp.accessProperty(l, "password", &comp.password)
216 func l_comp_auth_language(l *lua.LState) int {
217 comp := getCompAuth(l)
218 return comp.accessProperty(l, "language", &comp.language)
221 func l_comp_auth_version(l *lua.LState) int {
222 comp := getCompAuth(l)
223 return comp.accessProperty(l, "version", &comp.version)
226 func l_comp_auth_state(l *lua.LState) int {
227 comp := getCompAuth(l)
231 l.Push(lua.LString("init"))
233 l.Push(lua.LString("requested"))
235 l.Push(lua.LString("verified"))
237 l.Push(lua.LString("active"))
239 l.Push(lua.LString("error"))
240 l.Push(lua.LString(comp.err))