+++ /dev/null
-package main
-
-import (
- "github.com/HimbeerserverDE/srp"
- "github.com/anon55555/mt"
- "github.com/dragonfireclient/hydra-dragonfire/convert"
- "github.com/yuin/gopher-lua"
- "strings"
- "time"
-)
-
-type authState uint8
-
-const (
- asInit authState = iota
- asRequested
- asVerified
- asActive
- asError
-)
-
-type Auth struct {
- client *Client
- username string
- password string
- language string
- version string
- state authState
- err string
- srpBytesA, bytesA []byte
- userdata *lua.LUserData
-}
-
-var authFuncs = map[string]lua.LGFunction{
- "username": l_auth_username,
- "password": l_auth_password,
- "language": l_auth_language,
- "version": l_auth_version,
- "state": l_auth_state,
-}
-
-func getAuth(l *lua.LState) *Auth {
- return l.CheckUserData(1).Value.(*Auth)
-}
-
-func (auth *Auth) create(client *Client, l *lua.LState) {
- if client.state != csNew {
- panic("can't add auth component after connect")
- }
-
- auth.client = client
- auth.language = "en_US"
- auth.version = "hydra-dragonfire"
- auth.state = asInit
- auth.userdata = l.NewUserData()
- auth.userdata.Value = auth
- l.SetMetatable(auth.userdata, l.GetTypeMetatable("hydra.auth"))
-}
-
-func (auth *Auth) push() lua.LValue {
- return auth.userdata
-}
-
-func (auth *Auth) connect() {
- if auth.username == "" {
- panic("missing username")
- }
-
- go func() {
- for auth.client.state == csConnected && auth.state == asInit {
- auth.client.conn.SendCmd(&mt.ToSrvInit{
- SerializeVer: serializeVer,
- MinProtoVer: protoVer,
- MaxProtoVer: protoVer,
- PlayerName: auth.username,
- })
- time.Sleep(500 * time.Millisecond)
- }
- }()
-}
-
-func (auth *Auth) fail(err string) {
- auth.err = err
- auth.state = asError
- auth.client.closeConn()
-}
-
-func (auth *Auth) checkState(state authState, pkt *mt.Pkt) bool {
- if auth.state == state {
- return true
- }
-
- auth.fail("received " + string(convert.PushPktType(pkt)) + " in invalid state")
- return false
-}
-
-func (auth *Auth) process(pkt *mt.Pkt) {
- if auth.state == asError {
- return
- }
-
- switch cmd := pkt.Cmd.(type) {
- case *mt.ToCltHello:
- if !auth.checkState(asInit, pkt) {
- return
- }
-
- if cmd.SerializeVer != 28 {
- auth.fail("unsupported serialize version")
- return
- }
-
- if cmd.AuthMethods == mt.FirstSRP {
- salt, verifier, err := srp.NewClient([]byte(strings.ToLower(auth.username)), []byte(auth.password))
- if err != nil {
- auth.fail(err.Error())
- return
- }
-
- auth.client.conn.SendCmd(&mt.ToSrvFirstSRP{
- Salt: salt,
- Verifier: verifier,
- EmptyPasswd: auth.password == "",
- })
- auth.state = asVerified
- } else if cmd.AuthMethods == mt.SRP {
- var err error
- auth.srpBytesA, auth.bytesA, err = srp.InitiateHandshake()
- if err != nil {
- auth.fail(err.Error())
- return
- }
-
- auth.client.conn.SendCmd(&mt.ToSrvSRPBytesA{
- A: auth.srpBytesA,
- NoSHA1: true,
- })
- auth.state = asRequested
- } else {
- auth.fail("invalid auth methods")
- return
- }
-
- case *mt.ToCltSRPBytesSaltB:
- if !auth.checkState(asRequested, pkt) {
- return
- }
-
- srpBytesK, err := srp.CompleteHandshake(auth.srpBytesA, auth.bytesA, []byte(strings.ToLower(auth.username)), []byte(auth.password), cmd.Salt, cmd.B)
- if err != nil {
- auth.fail(err.Error())
- return
- }
-
- M := srp.ClientProof([]byte(auth.username), cmd.Salt, auth.srpBytesA, cmd.B, srpBytesK)
- auth.srpBytesA = []byte{}
- auth.bytesA = []byte{}
-
- if M == nil {
- auth.fail("srp safety check fail")
- return
- }
-
- auth.client.conn.SendCmd(&mt.ToSrvSRPBytesM{
- M: M,
- })
- auth.state = asVerified
-
- case *mt.ToCltAcceptAuth:
- auth.client.conn.SendCmd(&mt.ToSrvInit2{Lang: auth.language})
-
- case *mt.ToCltTimeOfDay:
- if auth.state == asActive {
- return
- }
-
- if !auth.checkState(asVerified, pkt) {
- return
- }
-
- auth.client.conn.SendCmd(&mt.ToSrvCltReady{
- Major: 5,
- Minor: 6,
- Patch: 0,
- Reserved: 0,
- Formspec: 4,
- Version: auth.version,
- })
- auth.state = asActive
- }
-}
-
-func (auth *Auth) accessProperty(l *lua.LState, key string, ptr *string) int {
- if str, ok := l.Get(2).(lua.LString); ok {
- if auth.client.state != csNew {
- panic("can't change " + key + " after connecting")
- }
- *ptr = string(str)
- return 0
- } else {
- l.Push(lua.LString(*ptr))
- return 1
- }
-}
-
-func l_auth_username(l *lua.LState) int {
- auth := getAuth(l)
- return auth.accessProperty(l, "username", &auth.username)
-}
-
-func l_auth_password(l *lua.LState) int {
- auth := getAuth(l)
- return auth.accessProperty(l, "password", &auth.password)
-}
-
-func l_auth_language(l *lua.LState) int {
- auth := getAuth(l)
- return auth.accessProperty(l, "language", &auth.language)
-}
-
-func l_auth_version(l *lua.LState) int {
- auth := getAuth(l)
- return auth.accessProperty(l, "version", &auth.version)
-}
-
-func l_auth_state(l *lua.LState) int {
- auth := getAuth(l)
-
- switch auth.state {
- case asInit:
- l.Push(lua.LString("init"))
- case asRequested:
- l.Push(lua.LString("requested"))
- case asVerified:
- l.Push(lua.LString("verified"))
- case asActive:
- l.Push(lua.LString("active"))
- case asError:
- l.Push(lua.LString("error"))
- l.Push(lua.LString(auth.err))
- return 2
- }
-
- return 1
-}