mirror of
https://github.com/Mezeporta/Erupe.git
synced 2025-12-15 00:15:08 +01:00
121 lines
2.7 KiB
Go
121 lines
2.7 KiB
Go
package signserver
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/hex"
|
|
"net"
|
|
"sync"
|
|
|
|
"github.com/Andoryuuta/Erupe/network"
|
|
"github.com/Andoryuuta/byteframe"
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
// Session holds state for the sign server connection.
|
|
type Session struct {
|
|
sync.Mutex
|
|
logger *zap.Logger
|
|
sid int
|
|
server *Server
|
|
rawConn *net.Conn
|
|
cryptConn *network.CryptConn
|
|
}
|
|
|
|
func (s *Session) fail() {
|
|
s.server.Lock()
|
|
delete(s.server.sessions, s.sid)
|
|
s.server.Unlock()
|
|
|
|
}
|
|
|
|
func (s *Session) work() {
|
|
for {
|
|
pkt, err := s.cryptConn.ReadPacket()
|
|
if err != nil {
|
|
s.fail()
|
|
return
|
|
}
|
|
|
|
err = s.handlePacket(pkt)
|
|
if err != nil {
|
|
s.fail()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *Session) handlePacket(pkt []byte) error {
|
|
sugar := s.logger.Sugar()
|
|
|
|
bf := byteframe.NewByteFrameFromBytes(pkt)
|
|
reqType := string(bf.ReadNullTerminatedBytes())
|
|
switch reqType {
|
|
case "DLTSKEYSIGN:100":
|
|
fallthrough
|
|
case "DSGN:100":
|
|
err := s.handleDSGNRequest(bf)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
case "DELETE:100":
|
|
loginTokenString := string(bf.ReadNullTerminatedBytes())
|
|
_ = loginTokenString
|
|
characterID := bf.ReadUint32()
|
|
|
|
sugar.Infof("Got delete request for character ID: %v\n", characterID)
|
|
sugar.Infof("remaining unknown data:\n%s\n", hex.Dump(bf.DataFromCurrent()))
|
|
default:
|
|
sugar.Infof("Got unknown request type %s, data:\n%s\n", reqType, hex.Dump(bf.DataFromCurrent()))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *Session) handleDSGNRequest(bf *byteframe.ByteFrame) error {
|
|
|
|
reqUsername := string(bf.ReadNullTerminatedBytes())
|
|
reqPassword := string(bf.ReadNullTerminatedBytes())
|
|
reqUnk := string(bf.ReadNullTerminatedBytes())
|
|
|
|
s.server.logger.Info(
|
|
"Got sign in request",
|
|
zap.String("reqUsername", reqUsername),
|
|
zap.String("reqPassword", reqPassword),
|
|
zap.String("reqUnk", reqUnk),
|
|
)
|
|
|
|
// TODO(Andoryuuta): remove plaintext password storage if this ever becomes more than a toy project.
|
|
var (
|
|
id int
|
|
password string
|
|
)
|
|
err := s.server.db.QueryRow("SELECT id, password FROM users WHERE username = $1", reqUsername).Scan(&id, &password)
|
|
var serverRespBytes []byte
|
|
switch {
|
|
case err == sql.ErrNoRows:
|
|
s.logger.Info("Account not found", zap.String("reqUsername", reqUsername))
|
|
serverRespBytes = makeSignInFailureResp(SIGN_EAUTH)
|
|
break
|
|
case err != nil:
|
|
serverRespBytes = makeSignInFailureResp(SIGN_EABORT)
|
|
s.logger.Warn("Got error on SQL query", zap.Error(err))
|
|
break
|
|
default:
|
|
if reqPassword == password {
|
|
s.logger.Info("Passwords match!")
|
|
serverRespBytes = s.makeSignInResp(reqUsername)
|
|
} else {
|
|
s.logger.Info("Passwords don't match!")
|
|
serverRespBytes = makeSignInFailureResp(SIGN_EPASS)
|
|
}
|
|
|
|
}
|
|
|
|
err = s.cryptConn.SendPacket(serverRespBytes)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|