Merge branch 'main' into pr/sign-v2

This commit is contained in:
wish
2022-11-07 08:28:37 +11:00
10 changed files with 136 additions and 69 deletions

13
common/token/token.go Normal file
View File

@@ -0,0 +1,13 @@
package token
import "math/rand"
// Generate returns an alphanumeric token of specified length
func Generate(length int) string {
var chars = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
b := make([]rune, length)
for i := range b {
b[i] = chars[rand.Intn(len(chars))]
}
return string(b)
}

View File

@@ -3,13 +3,14 @@
"BinPath": "bin", "BinPath": "bin",
"DisableSoftCrash": false, "DisableSoftCrash": false,
"FeaturedWeapons": 1, "FeaturedWeapons": 1,
"HideLoginNotice": true,
"LoginNotice": "<BODY><CENTER><SIZE_3><C_4>Welcome to Erupe SU9.1!<BR><BODY><LEFT><SIZE_2><C_5>Erupe is experimental software<C_7>, we are not liable for any<BR><BODY>issues caused by installing the software!<BR><BODY><BR><BODY><C_4>■Report bugs on Discord!<C_7><BR><BODY><BR><BODY><C_4>■Test everything!<C_7><BR><BODY><BR><BODY><C_4>■Don't talk to softlocking NPCs!<C_7><BR><BODY><BR><BODY><C_4>■Fork the code on GitHub!<C_7><BR><BODY><BR><BODY>Thank you to all of the contributors,<BR><BODY><BR><BODY>this wouldn't exist without you.",
"PatchServerManifest": "",
"PatchServerFile": "",
"ScreenshotAPIURL": "",
"DevMode": true, "DevMode": true,
"DevModeOptions": { "DevModeOptions": {
"PatchServerManifest": "",
"PatchServerFile": "",
"AutoCreateAccount": true, "AutoCreateAccount": true,
"HideLoginNotice": false,
"LoginNotice": "<BODY><CENTER><SIZE_3><C_4>Welcome to Erupe SU9.1!<BR><BODY><LEFT><SIZE_2><C_5>Erupe is experimental software<C_7>, we are not liable for any<BR><BODY>issues caused by installing the software!<BR><BODY><BR><BODY><C_4>■Report bugs on Discord!<C_7><BR><BODY><BR><BODY><C_4>■Test everything!<C_7><BR><BODY><BR><BODY><C_4>■Don't talk to softlocking NPCs!<C_7><BR><BODY><BR><BODY><C_4>■Fork the code on GitHub!<C_7><BR><BODY><BR><BODY>Thank you to all of the contributors,<BR><BODY><BR><BODY>this wouldn't exist without you.",
"CleanDB": false, "CleanDB": false,
"MaxLauncherHR": false, "MaxLauncherHR": false,
"LogInboundMessages": false, "LogInboundMessages": false,

View File

@@ -12,11 +12,16 @@ import (
// Config holds the global server-wide config. // Config holds the global server-wide config.
type Config struct { type Config struct {
Host string `mapstructure:"Host"` Host string `mapstructure:"Host"`
BinPath string `mapstructure:"BinPath"` BinPath string `mapstructure:"BinPath"`
DisableSoftCrash bool // Disables the 'Press Return to exit' dialog allowing scripts to reboot the server automatically DisableSoftCrash bool // Disables the 'Press Return to exit' dialog allowing scripts to reboot the server automatically
FeaturedWeapons int // Number of Active Feature weapons to generate daily FeaturedWeapons int // Number of Active Feature weapons to generate daily
DevMode bool HideLoginNotice bool // Hide the Erupe notice on login
LoginNotice string // MHFML string of the login notice displayed
PatchServerManifest string // Manifest patch server override
PatchServerFile string // File patch server override
ScreenshotAPIURL string // Destination for screenshots uploaded to BBS
DevMode bool
DevModeOptions DevModeOptions DevModeOptions DevModeOptions
Discord Discord Discord Discord
@@ -32,24 +37,20 @@ type Config struct {
// DevModeOptions holds various debug/temporary options for use while developing Erupe. // DevModeOptions holds various debug/temporary options for use while developing Erupe.
type DevModeOptions struct { type DevModeOptions struct {
PatchServerManifest string // Manifest patch server override AutoCreateAccount bool // Automatically create accounts if they don't exist
PatchServerFile string // File patch server override CleanDB bool // Automatically wipes the DB on server reset.
AutoCreateAccount bool // Automatically create accounts if they don't exist MaxLauncherHR bool // Sets the HR returned in the launcher to HR7 so that you can join non-beginner worlds.
HideLoginNotice bool // Hide the Erupe notice on login LogInboundMessages bool // Log all messages sent to the server
LoginNotice string // MHFML string of the login notice displayed LogOutboundMessages bool // Log all messages sent to the clients
CleanDB bool // Automatically wipes the DB on server reset. MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled
MaxLauncherHR bool // Sets the HR returned in the launcher to HR7 so that you can join non-beginner worlds. DivaEvent int // Diva Defense event status
LogInboundMessages bool // Log all messages sent to the server FestaEvent int // Hunter's Festa event status
LogOutboundMessages bool // Log all messages sent to the clients TournamentEvent int // VS Tournament event status
MaxHexdumpLength int // Maximum number of bytes printed when logs are enabled MezFesEvent bool // MezFes status
DivaEvent int // Diva Defense event status MezFesAlt bool // Swaps out Volpakkun for Tokotoko
FestaEvent int // Hunter's Festa event status DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!)
TournamentEvent int // VS Tournament event status DisableMailItems bool // Hack to prevent english versions of MHF from crashing
MezFesEvent bool // MezFes status QuestDebugTools bool // Enable various quest debug logs
MezFesAlt bool // Swaps out Volpakkun for Tokotoko
DisableTokenCheck bool // Disables checking login token exists in the DB (security risk!)
DisableMailItems bool // Hack to prevent english versions of MHF from crashing
QuestDebugTools bool // Enable various quest debug logs
SaveDumps SaveDumpOptions SaveDumps SaveDumpOptions
} }

View File

@@ -1,15 +1,24 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/common/bfutil"
"erupe-ce/common/stringsupport"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
// MsgMhfApplyBbsArticle represents the MSG_MHF_APPLY_BBS_ARTICLE // MsgMhfApplyBbsArticle represents the MSG_MHF_APPLY_BBS_ARTICLE
type MsgMhfApplyBbsArticle struct{} type MsgMhfApplyBbsArticle struct {
AckHandle uint32
Unk0 uint32
Unk1 []byte
Name string
Title string
Description string
}
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
func (m *MsgMhfApplyBbsArticle) Opcode() network.PacketID { func (m *MsgMhfApplyBbsArticle) Opcode() network.PacketID {
@@ -18,7 +27,13 @@ func (m *MsgMhfApplyBbsArticle) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfApplyBbsArticle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfApplyBbsArticle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
return errors.New("NOT IMPLEMENTED") m.AckHandle = bf.ReadUint32()
m.Unk0 = bf.ReadUint32()
m.Unk1 = bf.ReadBytes(16)
m.Name = stringsupport.SJISToUTF8(bfutil.UpToNull(bf.ReadBytes(32)))
m.Title = stringsupport.SJISToUTF8(bfutil.UpToNull(bf.ReadBytes(128)))
m.Description = stringsupport.SJISToUTF8(bfutil.UpToNull(bf.ReadBytes(256)))
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

@@ -1,15 +1,18 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
// MsgMhfGetBbsSnsStatus represents the MSG_MHF_GET_BBS_SNS_STATUS // MsgMhfGetBbsSnsStatus represents the MSG_MHF_GET_BBS_SNS_STATUS
type MsgMhfGetBbsSnsStatus struct{} type MsgMhfGetBbsSnsStatus struct {
AckHandle uint32
Unk []byte
}
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
func (m *MsgMhfGetBbsSnsStatus) Opcode() network.PacketID { func (m *MsgMhfGetBbsSnsStatus) Opcode() network.PacketID {
@@ -18,7 +21,9 @@ func (m *MsgMhfGetBbsSnsStatus) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfGetBbsSnsStatus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfGetBbsSnsStatus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
return errors.New("NOT IMPLEMENTED") m.AckHandle = bf.ReadUint32()
m.Unk = bf.ReadBytes(12)
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

@@ -1,15 +1,18 @@
package mhfpacket package mhfpacket
import ( import (
"errors" "errors"
"erupe-ce/network/clientctx"
"erupe-ce/network"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/network"
"erupe-ce/network/clientctx"
) )
// MsgMhfGetBbsUserStatus represents the MSG_MHF_GET_BBS_USER_STATUS // MsgMhfGetBbsUserStatus represents the MSG_MHF_GET_BBS_USER_STATUS
type MsgMhfGetBbsUserStatus struct{} type MsgMhfGetBbsUserStatus struct {
AckHandle uint32
Unk []byte
}
// Opcode returns the ID associated with this packet type. // Opcode returns the ID associated with this packet type.
func (m *MsgMhfGetBbsUserStatus) Opcode() network.PacketID { func (m *MsgMhfGetBbsUserStatus) Opcode() network.PacketID {
@@ -18,7 +21,9 @@ func (m *MsgMhfGetBbsUserStatus) Opcode() network.PacketID {
// Parse parses the packet from binary // Parse parses the packet from binary
func (m *MsgMhfGetBbsUserStatus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { func (m *MsgMhfGetBbsUserStatus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error {
return errors.New("NOT IMPLEMENTED") m.AckHandle = bf.ReadUint32()
m.Unk = bf.ReadBytes(12)
return nil
} }
// Build builds a binary packet from the current data. // Build builds a binary packet from the current data.

View File

@@ -1495,10 +1495,6 @@ func handleMsgMhfInfoScenarioCounter(s *Session, p mhfpacket.MHFPacket) {
doAckBufSucceed(s, pkt.AckHandle, resp.Data()) doAckBufSucceed(s, pkt.AckHandle, resp.Data())
} }
func handleMsgMhfGetBbsSnsStatus(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfApplyBbsArticle(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetEtcPoints(s *Session, p mhfpacket.MHFPacket) { func handleMsgMhfGetEtcPoints(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetEtcPoints) pkt := p.(*mhfpacket.MsgMhfGetEtcPoints)

View File

@@ -0,0 +1,41 @@
package channelserver
import (
"erupe-ce/common/byteframe"
"erupe-ce/common/stringsupport"
"erupe-ce/common/token"
"erupe-ce/network/mhfpacket"
)
func handleMsgMhfGetBbsUserStatus(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetBbsUserStatus)
bf := byteframe.NewByteFrame()
bf.WriteUint32(200)
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteUint32(0)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func handleMsgMhfGetBbsSnsStatus(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfGetBbsSnsStatus)
bf := byteframe.NewByteFrame()
bf.WriteUint32(200)
bf.WriteUint32(401)
bf.WriteUint32(401)
bf.WriteUint32(0)
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}
func handleMsgMhfApplyBbsArticle(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfApplyBbsArticle)
bf := byteframe.NewByteFrame()
articleToken := token.Generate(40)
bf.WriteUint32(200)
bf.WriteUint32(80)
bf.WriteUint32(0)
bf.WriteUint32(0)
bf.WriteBytes(stringsupport.PaddedString(articleToken, 64, false))
bf.WriteBytes(stringsupport.PaddedString(s.server.erupeConfig.ScreenshotAPIURL, 64, false))
doAckBufSucceed(s, pkt.AckHandle, bf.Data())
}

View File

@@ -54,5 +54,3 @@ func handleMsgSysGetUserBinary(s *Session, p mhfpacket.MHFPacket) {
} }
func handleMsgSysNotifyUserBinary(s *Session, p mhfpacket.MHFPacket) {} func handleMsgSysNotifyUserBinary(s *Session, p mhfpacket.MHFPacket) {}
func handleMsgMhfGetBbsUserStatus(s *Session, p mhfpacket.MHFPacket) {}

View File

@@ -4,6 +4,7 @@ import (
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
ps "erupe-ce/common/pascalstring" ps "erupe-ce/common/pascalstring"
"erupe-ce/common/stringsupport" "erupe-ce/common/stringsupport"
"erupe-ce/common/token"
"erupe-ce/server/channelserver" "erupe-ce/server/channelserver"
"fmt" "fmt"
"math/rand" "math/rand"
@@ -18,15 +19,6 @@ func makeSignInFailureResp(respID RespID) []byte {
return bf.Data() return bf.Data()
} }
func randSeq(n int) string {
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(len(letters))]
}
return string(b)
}
func (s *Session) makeSignInResp(uid int) []byte { func (s *Session) makeSignInResp(uid int) []byte {
returnExpiry := s.server.getReturnExpiry(uid) returnExpiry := s.server.getReturnExpiry(uid)
@@ -37,13 +29,13 @@ func (s *Session) makeSignInResp(uid int) []byte {
} }
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
token := randSeq(16) sessToken := token.Generate(16)
s.server.registerToken(uid, token) s.server.registerToken(uid, sessToken)
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
bf.WriteUint8(1) // resp_code bf.WriteUint8(1) // resp_code
if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.PatchServerManifest != "" && s.server.erupeConfig.DevModeOptions.PatchServerFile != "" { if s.server.erupeConfig.DevMode && s.server.erupeConfig.PatchServerManifest != "" && s.server.erupeConfig.PatchServerFile != "" {
bf.WriteUint8(2) bf.WriteUint8(2)
} else { } else {
bf.WriteUint8(0) bf.WriteUint8(0)
@@ -51,12 +43,12 @@ func (s *Session) makeSignInResp(uid int) []byte {
bf.WriteUint8(1) // entrance server count bf.WriteUint8(1) // entrance server count
bf.WriteUint8(uint8(len(chars))) // character count bf.WriteUint8(uint8(len(chars))) // character count
bf.WriteUint32(0xFFFFFFFF) // login_token_number bf.WriteUint32(0xFFFFFFFF) // login_token_number
bf.WriteBytes([]byte(token)) // login_token bf.WriteBytes([]byte(sessToken)) // login_token
bf.WriteUint32(uint32(time.Now().Unix())) // current time bf.WriteUint32(uint32(time.Now().Unix())) // current time
if s.server.erupeConfig.DevMode { if s.server.erupeConfig.DevMode {
if s.server.erupeConfig.DevModeOptions.PatchServerManifest != "" && s.server.erupeConfig.DevModeOptions.PatchServerFile != "" { if s.server.erupeConfig.PatchServerManifest != "" && s.server.erupeConfig.PatchServerFile != "" {
ps.Uint8(bf, s.server.erupeConfig.DevModeOptions.PatchServerManifest, false) ps.Uint8(bf, s.server.erupeConfig.PatchServerManifest, false)
ps.Uint8(bf, s.server.erupeConfig.DevModeOptions.PatchServerFile, false) ps.Uint8(bf, s.server.erupeConfig.PatchServerFile, false)
} }
} }
ps.Uint8(bf, fmt.Sprintf("%s:%d", s.server.erupeConfig.Host, s.server.erupeConfig.Entrance.Port), false) ps.Uint8(bf, fmt.Sprintf("%s:%d", s.server.erupeConfig.Host, s.server.erupeConfig.Entrance.Port), false)
@@ -111,11 +103,11 @@ func (s *Session) makeSignInResp(uid int) []byte {
} }
} }
if s.server.erupeConfig.DevModeOptions.HideLoginNotice { if s.server.erupeConfig.HideLoginNotice {
bf.WriteUint8(0) bf.WriteUint8(0)
} else { } else {
bf.WriteUint8(1) // Notice count bf.WriteUint8(1) // Notice count
noticeText := s.server.erupeConfig.DevModeOptions.LoginNotice noticeText := s.server.erupeConfig.LoginNotice
ps.Uint32(bf, noticeText, true) ps.Uint32(bf, noticeText, true)
} }