refactor: standardize logging on zap across all packages

Replace all fmt.Printf/Println and log.Printf/Fatal with structured
zap.Logger calls to eliminate inconsistent logging (anti-pattern #12).

- network/crypt_conn: inject logger via NewCryptConn, replace 6 fmt calls
- signserver/session: use existing s.logger for debug packet dumps
- entranceserver: use s.logger for inbound/outbound debug logging
- api/utils: accept logger param in verifyPath, replace fmt.Println
- api/endpoints: use s.logger for screenshot path diagnostics
- config: replace log.Fatal with error return in getOutboundIP4
- deltacomp: replace log.Printf with zap.L() global logger
This commit is contained in:
Houmgaor
2026-02-20 18:59:12 +01:00
parent e5133e5dcf
commit 06cb3afa57
15 changed files with 134 additions and 117 deletions

View File

@@ -1,7 +1,7 @@
package _config package _config
import ( import (
"log" "fmt"
"net" "net"
"strings" "strings"
@@ -305,19 +305,18 @@ func (c *EntranceChannelInfo) IsEnabled() bool {
return *c.Enabled return *c.Enabled
} }
// getOutboundIP4 gets the preferred outbound ip4 of this machine // getOutboundIP4 gets the preferred outbound ip4 of this machine
// From https://stackoverflow.com/a/37382208 // From https://stackoverflow.com/a/37382208
func getOutboundIP4() net.IP { func getOutboundIP4() (net.IP, error) {
conn, err := net.Dial("udp4", "8.8.8.8:80") conn, err := net.Dial("udp4", "8.8.8.8:80")
if err != nil { if err != nil {
log.Fatal(err) return nil, fmt.Errorf("detecting outbound IP: %w", err)
} }
defer func() { _ = conn.Close() }() defer func() { _ = conn.Close() }()
localAddr := conn.LocalAddr().(*net.UDPAddr) localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP.To4() return localAddr.IP.To4(), nil
} }
// LoadConfig loads the given config toml file. // LoadConfig loads the given config toml file.
@@ -342,7 +341,11 @@ func LoadConfig() (*Config, error) {
} }
if c.Host == "" { if c.Host == "" {
c.Host = getOutboundIP4().To4().String() ip, err := getOutboundIP4()
if err != nil {
return nil, fmt.Errorf("failed to detect host IP: %w", err)
}
c.Host = ip.To4().String()
} }
for i := range versionStrings { for i := range versionStrings {
@@ -365,4 +368,3 @@ func LoadConfig() (*Config, error) {
return c, nil return c, nil
} }

View File

@@ -72,7 +72,7 @@ func TestLoadConfigClientModeMapping(t *testing.T) {
// TestLoadConfigFeatureWeaponConstraint tests MinFeatureWeapons > MaxFeatureWeapons constraint // TestLoadConfigFeatureWeaponConstraint tests MinFeatureWeapons > MaxFeatureWeapons constraint
func TestLoadConfigFeatureWeaponConstraint(t *testing.T) { func TestLoadConfigFeatureWeaponConstraint(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
minWeapons int minWeapons int
maxWeapons int maxWeapons int
expected int expected int
@@ -107,7 +107,11 @@ func TestLoadConfigDefaultHost(t *testing.T) {
// When Host is empty, it should be set to the outbound IP // When Host is empty, it should be set to the outbound IP
if cfg.Host == "" { if cfg.Host == "" {
// Simulate the logic: if empty, set to outbound IP // Simulate the logic: if empty, set to outbound IP
cfg.Host = getOutboundIP4().To4().String() ip, err := getOutboundIP4()
if err != nil {
t.Fatalf("getOutboundIP4() error: %v", err)
}
cfg.Host = ip.To4().String()
if cfg.Host == "" { if cfg.Host == "" {
t.Error("Host should be set to outbound IP, got empty string") t.Error("Host should be set to outbound IP, got empty string")
} }
@@ -271,12 +275,12 @@ func TestEntranceServerConfig(t *testing.T) {
Port: 10000, Port: 10000,
Entries: []EntranceServerInfo{ Entries: []EntranceServerInfo{
{ {
IP: "192.168.1.100", IP: "192.168.1.100",
Type: 1, // open Type: 1, // open
Season: 0, // green Season: 0, // green
Recommended: 1, Recommended: 1,
Name: "Main Server", Name: "Main Server",
Description: "Main hunting server", Description: "Main hunting server",
AllowedClientFlags: 8192, AllowedClientFlags: 8192,
Channels: []EntranceChannelInfo{ Channels: []EntranceChannelInfo{
{Port: 10001, MaxPlayers: 4, CurrentPlayers: 2}, {Port: 10001, MaxPlayers: 4, CurrentPlayers: 2},
@@ -486,9 +490,9 @@ func BenchmarkConfigCreation(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_ = &Config{ _ = &Config{
Host: "localhost", Host: "localhost",
Language: "en", Language: "en",
ClientMode: "ZZ", ClientMode: "ZZ",
RealClientMode: ZZ, RealClientMode: ZZ,
} }
} }

View File

@@ -108,14 +108,14 @@ func TestVersionStringsContent(t *testing.T) {
index int index int
expected string expected string
}{ }{
{0, "S1.0"}, // S1 {0, "S1.0"}, // S1
{14, "S10"}, // S10 {14, "S10"}, // S10
{15, "FW.1"}, // F1 {15, "FW.1"}, // F1
{19, "FW.5"}, // F5 {19, "FW.5"}, // F5
{20, "G1"}, // G1 {20, "G1"}, // G1
{38, "Z1"}, // Z1 {38, "Z1"}, // Z1
{39, "Z2"}, // Z2 {39, "Z2"}, // Z2
{40, "ZZ"}, // ZZ {40, "ZZ"}, // ZZ
} }
for _, tt := range tests { for _, tt := range tests {
@@ -127,7 +127,10 @@ func TestVersionStringsContent(t *testing.T) {
// TestGetOutboundIP4 tests IP detection // TestGetOutboundIP4 tests IP detection
func TestGetOutboundIP4(t *testing.T) { func TestGetOutboundIP4(t *testing.T) {
ip := getOutboundIP4() ip, err := getOutboundIP4()
if err != nil {
t.Fatalf("getOutboundIP4() returned error: %v", err)
}
if ip == nil { if ip == nil {
t.Error("getOutboundIP4() returned nil IP") t.Error("getOutboundIP4() returned nil IP")
} }
@@ -276,17 +279,17 @@ func TestDebugOptions(t *testing.T) {
// TestGameplayOptions verifies GameplayOptions struct // TestGameplayOptions verifies GameplayOptions struct
func TestGameplayOptions(t *testing.T) { func TestGameplayOptions(t *testing.T) {
opts := GameplayOptions{ opts := GameplayOptions{
MinFeatureWeapons: 2, MinFeatureWeapons: 2,
MaxFeatureWeapons: 10, MaxFeatureWeapons: 10,
MaximumNP: 999999, MaximumNP: 999999,
MaximumRP: 9999, MaximumRP: 9999,
MaximumFP: 999999999, MaximumFP: 999999999,
MezFesSoloTickets: 100, MezFesSoloTickets: 100,
MezFesGroupTickets: 50, MezFesGroupTickets: 50,
DisableHunterNavi: true, DisableHunterNavi: true,
EnableKaijiEvent: true, EnableKaijiEvent: true,
EnableHiganjimaEvent: false, EnableHiganjimaEvent: false,
EnableNierEvent: false, EnableNierEvent: false,
} }
if opts.MinFeatureWeapons != 2 { if opts.MinFeatureWeapons != 2 {
@@ -486,12 +489,12 @@ func TestEntrance(t *testing.T) {
// TestEntranceServerInfo verifies EntranceServerInfo struct // TestEntranceServerInfo verifies EntranceServerInfo struct
func TestEntranceServerInfo(t *testing.T) { func TestEntranceServerInfo(t *testing.T) {
info := EntranceServerInfo{ info := EntranceServerInfo{
IP: "192.168.1.1", IP: "192.168.1.1",
Type: 1, Type: 1,
Season: 0, Season: 0,
Recommended: 0, Recommended: 0,
Name: "Server 1", Name: "Server 1",
Description: "Main server", Description: "Main server",
AllowedClientFlags: 4096, AllowedClientFlags: 4096,
Channels: []EntranceChannelInfo{ Channels: []EntranceChannelInfo{
{Port: 10001, MaxPlayers: 4, CurrentPlayers: 2}, {Port: 10001, MaxPlayers: 4, CurrentPlayers: 2},
@@ -624,9 +627,9 @@ func TestGameplayOptionsConstraints(t *testing.T) {
{ {
name: "valid multipliers", name: "valid multipliers",
opts: GameplayOptions{ opts: GameplayOptions{
HRPMultiplier: 1.5, HRPMultiplier: 1.5,
GRPMultiplier: 1.2, GRPMultiplier: 1.2,
ZennyMultiplier: 1.0, ZennyMultiplier: 1.0,
MaterialMultiplier: 1.3, MaterialMultiplier: 1.3,
}, },
ok: true, ok: true,
@@ -671,7 +674,7 @@ func TestModeValueRanges(t *testing.T) {
// TestConfigDefaults tests default configuration creation // TestConfigDefaults tests default configuration creation
func TestConfigDefaults(t *testing.T) { func TestConfigDefaults(t *testing.T) {
cfg := &Config{ cfg := &Config{
ClientMode: "ZZ", ClientMode: "ZZ",
RealClientMode: ZZ, RealClientMode: ZZ,
} }
@@ -696,7 +699,6 @@ func BenchmarkModeString(b *testing.B) {
func BenchmarkGetOutboundIP4(b *testing.B) { func BenchmarkGetOutboundIP4(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_ = getOutboundIP4() _, _ = getOutboundIP4()
} }
} }

View File

@@ -5,9 +5,10 @@ import (
"errors" "errors"
"erupe-ce/config" "erupe-ce/config"
"erupe-ce/network/crypto" "erupe-ce/network/crypto"
"fmt"
"io" "io"
"net" "net"
"go.uber.org/zap"
) )
// Conn defines the interface for a packet-based connection. // Conn defines the interface for a packet-based connection.
@@ -23,6 +24,7 @@ type Conn interface {
// CryptConn represents a MHF encrypted two-way connection, // CryptConn represents a MHF encrypted two-way connection,
// it automatically handles encryption, decryption, and key rotation via it's methods. // it automatically handles encryption, decryption, and key rotation via it's methods.
type CryptConn struct { type CryptConn struct {
logger *zap.Logger
conn net.Conn conn net.Conn
realClientMode _config.Mode realClientMode _config.Mode
readKeyRot uint32 readKeyRot uint32
@@ -33,8 +35,12 @@ type CryptConn struct {
} }
// NewCryptConn creates a new CryptConn with proper default values. // NewCryptConn creates a new CryptConn with proper default values.
func NewCryptConn(conn net.Conn, mode _config.Mode) *CryptConn { func NewCryptConn(conn net.Conn, mode _config.Mode, logger *zap.Logger) *CryptConn {
if logger == nil {
logger = zap.NewNop()
}
cc := &CryptConn{ cc := &CryptConn{
logger: logger,
conn: conn, conn: conn,
realClientMode: mode, realClientMode: mode,
readKeyRot: 995117, readKeyRot: 995117,
@@ -80,18 +86,19 @@ func (cc *CryptConn) ReadPacket() ([]byte, error) {
out, combinedCheck, check0, check1, check2 := crypto.Crypto(encryptedPacketBody, cc.readKeyRot, false, nil) out, combinedCheck, check0, check1, check2 := crypto.Crypto(encryptedPacketBody, cc.readKeyRot, false, nil)
if cph.Check0 != check0 || cph.Check1 != check1 || cph.Check2 != check2 { if cph.Check0 != check0 || cph.Check1 != check1 || cph.Check2 != check2 {
fmt.Printf("got c0 %X, c1 %X, c2 %X\n", check0, check1, check2) cc.logger.Warn("Crypto checksum mismatch",
fmt.Printf("want c0 %X, c1 %X, c2 %X\n", cph.Check0, cph.Check1, cph.Check2) zap.String("got", hex.EncodeToString([]byte{byte(check0 >> 8), byte(check0), byte(check1 >> 8), byte(check1), byte(check2 >> 8), byte(check2)})),
fmt.Printf("headerData:\n%s\n", hex.Dump(headerData)) zap.String("want", hex.EncodeToString([]byte{byte(cph.Check0 >> 8), byte(cph.Check0), byte(cph.Check1 >> 8), byte(cph.Check1), byte(cph.Check2 >> 8), byte(cph.Check2)})),
fmt.Printf("encryptedPacketBody:\n%s\n", hex.Dump(encryptedPacketBody)) zap.String("headerData", hex.Dump(headerData)),
zap.String("encryptedPacketBody", hex.Dump(encryptedPacketBody)),
)
// Attempt to bruteforce it. // Attempt to bruteforce it.
fmt.Println("Crypto out of sync? Attempting bruteforce") cc.logger.Warn("Crypto out of sync, attempting bruteforce")
for key := byte(0); key < 255; key++ { for key := byte(0); key < 255; key++ {
out, combinedCheck, check0, check1, check2 = crypto.Crypto(encryptedPacketBody, 0, false, &key) out, combinedCheck, check0, check1, check2 = crypto.Crypto(encryptedPacketBody, 0, false, &key)
//fmt.Printf("Key: 0x%X\n%s\n", key, hex.Dump(out))
if cph.Check0 == check0 && cph.Check1 == check1 && cph.Check2 == check2 { if cph.Check0 == check0 && cph.Check1 == check1 && cph.Check2 == check2 {
fmt.Printf("Bruceforce successful, override key: 0x%X\n", key) cc.logger.Info("Bruteforce successful", zap.Uint8("overrideKey", key))
// Try to fix key for subsequent packets? // Try to fix key for subsequent packets?
//cc.readKeyRot = (uint32(key) << 1) + 999983 //cc.readKeyRot = (uint32(key) << 1) + 999983

View File

@@ -2,9 +2,9 @@ package network
import ( import (
"bytes" "bytes"
"errors"
_config "erupe-ce/config" _config "erupe-ce/config"
"erupe-ce/network/crypto" "erupe-ce/network/crypto"
"errors"
"io" "io"
"net" "net"
"testing" "testing"
@@ -54,7 +54,7 @@ func (m *mockConn) SetWriteDeadline(t time.Time) error { return nil }
func TestNewCryptConn(t *testing.T) { func TestNewCryptConn(t *testing.T) {
mockConn := newMockConn(nil) mockConn := newMockConn(nil)
cc := NewCryptConn(mockConn, _config.ZZ) cc := NewCryptConn(mockConn, _config.ZZ, nil)
if cc == nil { if cc == nil {
t.Fatal("NewCryptConn() returned nil") t.Fatal("NewCryptConn() returned nil")
@@ -111,7 +111,7 @@ func TestCryptConn_SendPacket(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
mockConn := newMockConn(nil) mockConn := newMockConn(nil)
cc := NewCryptConn(mockConn, _config.ZZ) cc := NewCryptConn(mockConn, _config.ZZ, nil)
err := cc.SendPacket(tt.data) err := cc.SendPacket(tt.data)
if err != nil { if err != nil {
@@ -155,7 +155,7 @@ func TestCryptConn_SendPacket(t *testing.T) {
func TestCryptConn_SendPacket_MultiplePackets(t *testing.T) { func TestCryptConn_SendPacket_MultiplePackets(t *testing.T) {
mockConn := newMockConn(nil) mockConn := newMockConn(nil)
cc := NewCryptConn(mockConn, _config.ZZ) cc := NewCryptConn(mockConn, _config.ZZ, nil)
// Send first packet // Send first packet
err := cc.SendPacket([]byte{0x01, 0x02}) err := cc.SendPacket([]byte{0x01, 0x02})
@@ -190,7 +190,7 @@ func TestCryptConn_SendPacket_MultiplePackets(t *testing.T) {
func TestCryptConn_SendPacket_KeyRotation(t *testing.T) { func TestCryptConn_SendPacket_KeyRotation(t *testing.T) {
mockConn := newMockConn(nil) mockConn := newMockConn(nil)
cc := NewCryptConn(mockConn, _config.ZZ) cc := NewCryptConn(mockConn, _config.ZZ, nil)
initialKey := cc.sendKeyRot initialKey := cc.sendKeyRot
@@ -209,7 +209,7 @@ func TestCryptConn_SendPacket_KeyRotation(t *testing.T) {
func TestCryptConn_SendPacket_WriteError(t *testing.T) { func TestCryptConn_SendPacket_WriteError(t *testing.T) {
mockConn := newMockConn(nil) mockConn := newMockConn(nil)
mockConn.writeErr = errors.New("write error") mockConn.writeErr = errors.New("write error")
cc := NewCryptConn(mockConn, _config.ZZ) cc := NewCryptConn(mockConn, _config.ZZ, nil)
err := cc.SendPacket([]byte{0x01, 0x02, 0x03}) err := cc.SendPacket([]byte{0x01, 0x02, 0x03})
// Note: Current implementation doesn't return write error // Note: Current implementation doesn't return write error
@@ -244,7 +244,7 @@ func TestCryptConn_ReadPacket_Success(t *testing.T) {
packet := append(headerBytes, encryptedData...) packet := append(headerBytes, encryptedData...)
mockConn := newMockConn(packet) mockConn := newMockConn(packet)
cc := NewCryptConn(mockConn, _config.Z1) cc := NewCryptConn(mockConn, _config.Z1, nil)
// Set the key to match what we used for encryption // Set the key to match what we used for encryption
cc.readKeyRot = key cc.readKeyRot = key
@@ -290,7 +290,7 @@ func TestCryptConn_ReadPacket_KeyRotation(t *testing.T) {
packet := append(headerBytes, encryptedData...) packet := append(headerBytes, encryptedData...)
mockConn := newMockConn(packet) mockConn := newMockConn(packet)
cc := NewCryptConn(mockConn, _config.Z1) cc := NewCryptConn(mockConn, _config.Z1, nil)
cc.readKeyRot = key cc.readKeyRot = key
result, err := cc.ReadPacket() result, err := cc.ReadPacket()
@@ -330,7 +330,7 @@ func TestCryptConn_ReadPacket_NoKeyRotation(t *testing.T) {
packet := append(headerBytes, encryptedData...) packet := append(headerBytes, encryptedData...)
mockConn := newMockConn(packet) mockConn := newMockConn(packet)
cc := NewCryptConn(mockConn, _config.Z1) cc := NewCryptConn(mockConn, _config.Z1, nil)
cc.readKeyRot = key cc.readKeyRot = key
originalKeyRot := cc.readKeyRot originalKeyRot := cc.readKeyRot
@@ -352,7 +352,7 @@ func TestCryptConn_ReadPacket_NoKeyRotation(t *testing.T) {
func TestCryptConn_ReadPacket_HeaderReadError(t *testing.T) { func TestCryptConn_ReadPacket_HeaderReadError(t *testing.T) {
mockConn := newMockConn([]byte{0x01, 0x02}) // Only 2 bytes, header needs 14 mockConn := newMockConn([]byte{0x01, 0x02}) // Only 2 bytes, header needs 14
cc := NewCryptConn(mockConn, _config.ZZ) cc := NewCryptConn(mockConn, _config.ZZ, nil)
_, err := cc.ReadPacket() _, err := cc.ReadPacket()
if err == nil { if err == nil {
@@ -368,7 +368,7 @@ func TestCryptConn_ReadPacket_InvalidHeader(t *testing.T) {
// Create invalid header data (wrong endianness or malformed) // Create invalid header data (wrong endianness or malformed)
invalidHeader := []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} invalidHeader := []byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
mockConn := newMockConn(invalidHeader) mockConn := newMockConn(invalidHeader)
cc := NewCryptConn(mockConn, _config.ZZ) cc := NewCryptConn(mockConn, _config.ZZ, nil)
_, err := cc.ReadPacket() _, err := cc.ReadPacket()
if err == nil { if err == nil {
@@ -395,7 +395,7 @@ func TestCryptConn_ReadPacket_BodyReadError(t *testing.T) {
packet := append(headerBytes, incompleteBody...) packet := append(headerBytes, incompleteBody...)
mockConn := newMockConn(packet) mockConn := newMockConn(packet)
cc := NewCryptConn(mockConn, _config.Z1) cc := NewCryptConn(mockConn, _config.Z1, nil)
_, err := cc.ReadPacket() _, err := cc.ReadPacket()
if err == nil { if err == nil {
@@ -425,7 +425,7 @@ func TestCryptConn_ReadPacket_ChecksumMismatch(t *testing.T) {
packet := append(headerBytes, encryptedData...) packet := append(headerBytes, encryptedData...)
mockConn := newMockConn(packet) mockConn := newMockConn(packet)
cc := NewCryptConn(mockConn, _config.Z1) cc := NewCryptConn(mockConn, _config.Z1, nil)
cc.readKeyRot = key cc.readKeyRot = key
_, err := cc.ReadPacket() _, err := cc.ReadPacket()

View File

@@ -5,8 +5,8 @@ import (
"encoding/json" "encoding/json"
"encoding/xml" "encoding/xml"
"errors" "errors"
_config "erupe-ce/config"
"erupe-ce/common/gametime" "erupe-ce/common/gametime"
_config "erupe-ce/config"
"fmt" "fmt"
"image" "image"
"image/jpeg" "image/jpeg"
@@ -317,6 +317,7 @@ func (s *APIServer) ExportSave(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(save) _ = json.NewEncoder(w).Encode(save)
} }
// ScreenShotGet handles GET /api/ss/bbs/{id}, serving a previously uploaded // ScreenShotGet handles GET /api/ss/bbs/{id}, serving a previously uploaded
// screenshot image by its token ID. // screenshot image by its token ID.
func (s *APIServer) ScreenShotGet(w http.ResponseWriter, r *http.Request) { func (s *APIServer) ScreenShotGet(w http.ResponseWriter, r *http.Request) {
@@ -331,12 +332,12 @@ func (s *APIServer) ScreenShotGet(w http.ResponseWriter, r *http.Request) {
// Open the image file // Open the image file
safePath := s.erupeConfig.Screenshots.OutputDir safePath := s.erupeConfig.Screenshots.OutputDir
path := filepath.Join(safePath, fmt.Sprintf("%s.jpg", token)) path := filepath.Join(safePath, fmt.Sprintf("%s.jpg", token))
result, err := verifyPath(path, safePath) result, err := verifyPath(path, safePath, s.logger)
if err != nil { if err != nil {
fmt.Println("Error " + err.Error()) s.logger.Warn("Screenshot path verification failed", zap.Error(err))
} else { } else {
fmt.Println("Canonical: " + result) s.logger.Debug("Screenshot canonical path", zap.String("path", result))
file, err := os.Open(result) file, err := os.Open(result)
if err != nil { if err != nil {
@@ -353,6 +354,7 @@ func (s *APIServer) ScreenShotGet(w http.ResponseWriter, r *http.Request) {
} }
} }
} }
// ScreenShot handles POST /api/ss/bbs/upload.php, accepting a JPEG image // ScreenShot handles POST /api/ss/bbs/upload.php, accepting a JPEG image
// upload from the game client and saving it to the configured output directory. // upload from the game client and saving it to the configured output directory.
func (s *APIServer) ScreenShot(w http.ResponseWriter, r *http.Request) { func (s *APIServer) ScreenShot(w http.ResponseWriter, r *http.Request) {
@@ -402,7 +404,7 @@ func (s *APIServer) ScreenShot(w http.ResponseWriter, r *http.Request) {
safePath := s.erupeConfig.Screenshots.OutputDir safePath := s.erupeConfig.Screenshots.OutputDir
path := filepath.Join(safePath, fmt.Sprintf("%s.jpg", token)) path := filepath.Join(safePath, fmt.Sprintf("%s.jpg", token))
verified, err := verifyPath(path, safePath) verified, err := verifyPath(path, safePath, s.logger)
if err != nil { if err != nil {
writeResult("500") writeResult("500")
return return

View File

@@ -35,13 +35,12 @@ func NewTestConfig() *_config.Config {
MaxLauncherHR: false, MaxLauncherHR: false,
}, },
GameplayOptions: _config.GameplayOptions{ GameplayOptions: _config.GameplayOptions{
MezFesSoloTickets: 100, MezFesSoloTickets: 100,
MezFesGroupTickets: 50, MezFesGroupTickets: 50,
MezFesDuration: 604800, // 1 week MezFesDuration: 604800, // 1 week
MezFesSwitchMinigame: false, MezFesSwitchMinigame: false,
}, },
LoginNotices: []string{"Welcome to Erupe!"}, LoginNotices: []string{"Welcome to Erupe!"},
HideLoginNotice: false, HideLoginNotice: false,
} }
} }

View File

@@ -2,8 +2,9 @@ package api
import ( import (
"errors" "errors"
"fmt"
"path/filepath" "path/filepath"
"go.uber.org/zap"
) )
func inTrustedRoot(path string, trustedRoot string) error { func inTrustedRoot(path string, trustedRoot string) error {
@@ -16,20 +17,20 @@ func inTrustedRoot(path string, trustedRoot string) error {
return errors.New("path is outside of trusted root") return errors.New("path is outside of trusted root")
} }
func verifyPath(path string, trustedRoot string) (string, error) { func verifyPath(path string, trustedRoot string, logger *zap.Logger) (string, error) {
c := filepath.Clean(path) c := filepath.Clean(path)
fmt.Println("Cleaned path: " + c) logger.Debug("Cleaned path", zap.String("path", c))
r, err := filepath.EvalSymlinks(c) r, err := filepath.EvalSymlinks(c)
if err != nil { if err != nil {
fmt.Println("Error " + err.Error()) logger.Warn("Path verification failed", zap.Error(err))
return c, errors.New("unsafe or invalid path specified") return c, errors.New("unsafe or invalid path specified")
} }
err = inTrustedRoot(r, trustedRoot) err = inTrustedRoot(r, trustedRoot)
if err != nil { if err != nil {
fmt.Println("Error " + err.Error()) logger.Warn("Path outside trusted root", zap.Error(err))
return r, errors.New("unsafe or invalid path specified") return r, errors.New("unsafe or invalid path specified")
} else { } else {
return r, nil return r, nil

View File

@@ -3,8 +3,10 @@ package api
import ( import (
"os" "os"
"path/filepath" "path/filepath"
"testing"
"strings" "strings"
"testing"
"go.uber.org/zap"
) )
func TestInTrustedRoot(t *testing.T) { func TestInTrustedRoot(t *testing.T) {
@@ -131,7 +133,7 @@ func TestVerifyPath(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
result, err := verifyPath(tt.path, tt.trustedRoot) result, err := verifyPath(tt.path, tt.trustedRoot, zap.NewNop())
if (err != nil) != tt.wantErr { if (err != nil) != tt.wantErr {
t.Errorf("verifyPath() error = %v, wantErr %v", err, tt.wantErr) t.Errorf("verifyPath() error = %v, wantErr %v", err, tt.wantErr)
} }
@@ -171,7 +173,7 @@ func TestVerifyPathWithSymlinks(t *testing.T) {
} }
// Verify that symlink pointing outside is detected // Verify that symlink pointing outside is detected
_, err := verifyPath(symlinkPath, safeDir) _, err := verifyPath(symlinkPath, safeDir, zap.NewNop())
if err == nil { if err == nil {
t.Errorf("verifyPath() should reject symlink pointing outside trusted root") t.Errorf("verifyPath() should reject symlink pointing outside trusted root")
} }
@@ -188,7 +190,7 @@ func BenchmarkVerifyPath(b *testing.B) {
b.ResetTimer() b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, _ = verifyPath(testPath, safeDir) _, _ = verifyPath(testPath, safeDir, zap.NewNop())
} }
} }

View File

@@ -3,7 +3,8 @@ package deltacomp
import ( import (
"bytes" "bytes"
"io" "io"
"log"
"go.uber.org/zap"
) )
func checkReadUint8(r *bytes.Reader) (uint8, error) { func checkReadUint8(r *bytes.Reader) (uint8, error) {
@@ -77,7 +78,7 @@ func ApplyDataDiff(diff []byte, baseData []byte) []byte {
// Grow slice if it's required // Grow slice if it's required
if len(baseCopy) < dataOffset { if len(baseCopy) < dataOffset {
log.Printf("Slice smaller than data offset, growing slice...") zap.L().Warn("Slice smaller than data offset, growing slice")
baseCopy = append(baseCopy, make([]byte, (dataOffset+differentCount)-len(baseData))...) baseCopy = append(baseCopy, make([]byte, (dataOffset+differentCount)-len(baseData))...)
} else { } else {
length := len(baseCopy[dataOffset:]) length := len(baseCopy[dataOffset:])

View File

@@ -104,7 +104,7 @@ func (s *Server) handleEntranceServerConnection(conn net.Conn) {
} }
// Create a new encrypted connection handler and read a packet from it. // Create a new encrypted connection handler and read a packet from it.
cc := network.NewCryptConn(conn, s.erupeConfig.RealClientMode) cc := network.NewCryptConn(conn, s.erupeConfig.RealClientMode, s.logger)
pkt, err := cc.ReadPacket() pkt, err := cc.ReadPacket()
if err != nil { if err != nil {
s.logger.Warn("Error reading packet", zap.Error(err)) s.logger.Warn("Error reading packet", zap.Error(err))
@@ -112,7 +112,7 @@ func (s *Server) handleEntranceServerConnection(conn net.Conn) {
} }
if s.erupeConfig.DebugOptions.LogInboundMessages { if s.erupeConfig.DebugOptions.LogInboundMessages {
fmt.Printf("[Client] -> [Server]\nData [%d bytes]:\n%s\n", len(pkt), hex.Dump(pkt)) s.logger.Debug("Inbound packet", zap.Int("bytes", len(pkt)), zap.String("data", hex.Dump(pkt)))
} }
local := strings.Split(conn.RemoteAddr().String(), ":")[0] == "127.0.0.1" local := strings.Split(conn.RemoteAddr().String(), ":")[0] == "127.0.0.1"

View File

@@ -5,11 +5,11 @@ import (
"encoding/hex" "encoding/hex"
"erupe-ce/common/stringsupport" "erupe-ce/common/stringsupport"
_config "erupe-ce/config" _config "erupe-ce/config"
"fmt"
"net" "net"
"erupe-ce/common/byteframe" "erupe-ce/common/byteframe"
"erupe-ce/common/gametime" "erupe-ce/common/gametime"
"go.uber.org/zap"
) )
func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte { func encodeServerInfo(config *_config.Config, s *Server, local bool) []byte {
@@ -142,7 +142,7 @@ func makeSv2Resp(config *_config.Config, s *Server, local bool) []byte {
rawServerData := encodeServerInfo(config, s, local) rawServerData := encodeServerInfo(config, s, local)
if s.erupeConfig.DebugOptions.LogOutboundMessages { if s.erupeConfig.DebugOptions.LogOutboundMessages {
fmt.Printf("[Server] -> [Client]\nData [%d bytes]:\n%s\n", len(rawServerData), hex.Dump(rawServerData)) s.logger.Debug("Outbound SV2 response", zap.Int("bytes", len(rawServerData)), zap.String("data", hex.Dump(rawServerData)))
} }
respType := "SV2" respType := "SV2"
@@ -174,7 +174,7 @@ func makeUsrResp(pkt []byte, s *Server) []byte {
} }
if s.erupeConfig.DebugOptions.LogOutboundMessages { if s.erupeConfig.DebugOptions.LogOutboundMessages {
fmt.Printf("[Server] -> [Client]\nData [%d bytes]:\n%s\n", len(resp.Data()), hex.Dump(resp.Data())) s.logger.Debug("Outbound USR response", zap.Int("bytes", len(resp.Data())), zap.String("data", hex.Dump(resp.Data())))
} }
return makeHeader(resp.Data(), "USR", userEntries, 0x00) return makeHeader(resp.Data(), "USR", userEntries, 0x00)

View File

@@ -4,7 +4,6 @@ import (
"database/sql" "database/sql"
"encoding/hex" "encoding/hex"
"erupe-ce/common/stringsupport" "erupe-ce/common/stringsupport"
"fmt"
"net" "net"
"strings" "strings"
"sync" "sync"
@@ -40,7 +39,7 @@ func (s *Session) work() {
pkt, err := s.cryptConn.ReadPacket() pkt, err := s.cryptConn.ReadPacket()
if s.server.erupeConfig.DebugOptions.LogInboundMessages { if s.server.erupeConfig.DebugOptions.LogInboundMessages {
fmt.Printf("\n[Client] -> [Server]\nData [%d bytes]:\n%s\n", len(pkt), hex.Dump(pkt)) s.logger.Debug("Inbound packet", zap.Int("bytes", len(pkt)), zap.String("data", hex.Dump(pkt)))
} }
if err != nil { if err != nil {
@@ -84,7 +83,7 @@ func (s *Session) handlePacket(pkt []byte) error {
default: default:
s.logger.Warn("Unknown request", zap.String("reqType", reqType)) s.logger.Warn("Unknown request", zap.String("reqType", reqType))
if s.server.erupeConfig.DebugOptions.LogInboundMessages { if s.server.erupeConfig.DebugOptions.LogInboundMessages {
fmt.Printf("\n[Client] -> [Server]\nData [%d bytes]:\n%s\n", len(pkt), hex.Dump(pkt)) s.logger.Debug("Unknown inbound packet", zap.Int("bytes", len(pkt)), zap.String("data", hex.Dump(pkt)))
} }
} }
return nil return nil
@@ -108,7 +107,7 @@ func (s *Session) authenticate(username string, password string) {
bf.WriteUint8(uint8(resp)) bf.WriteUint8(uint8(resp))
} }
if s.server.erupeConfig.DebugOptions.LogOutboundMessages { if s.server.erupeConfig.DebugOptions.LogOutboundMessages {
fmt.Printf("\n[Server] -> [Client]\nData [%d bytes]:\n%s\n", len(bf.Data()), hex.Dump(bf.Data())) s.logger.Debug("Outbound packet", zap.Int("bytes", len(bf.Data())), zap.String("data", hex.Dump(bf.Data())))
} }
_ = s.cryptConn.SendPacket(bf.Data()) _ = s.cryptConn.SendPacket(bf.Data())
} }

View File

@@ -64,8 +64,8 @@ func (m *mockConn) RemoteAddr() net.Addr {
} }
func (m *mockConn) SetDeadline(t time.Time) error { return nil } func (m *mockConn) SetDeadline(t time.Time) error { return nil }
func (m *mockConn) SetReadDeadline(t time.Time) error { return nil } func (m *mockConn) SetReadDeadline(t time.Time) error { return nil }
func (m *mockConn) SetWriteDeadline(t time.Time) error { return nil } func (m *mockConn) SetWriteDeadline(t time.Time) error { return nil }
func TestSessionStruct(t *testing.T) { func TestSessionStruct(t *testing.T) {
logger := zap.NewNop() logger := zap.NewNop()
@@ -75,7 +75,7 @@ func TestSessionStruct(t *testing.T) {
logger: logger, logger: logger,
server: nil, server: nil,
rawConn: conn, rawConn: conn,
cryptConn: network.NewCryptConn(conn, _config.ZZ), cryptConn: network.NewCryptConn(conn, _config.ZZ, nil),
} }
if s.logger != logger { if s.logger != logger {
@@ -132,8 +132,7 @@ func TestSessionMutex(t *testing.T) {
func TestHandlePacketUnknownRequest(t *testing.T) { func TestHandlePacketUnknownRequest(t *testing.T) {
logger := zap.NewNop() logger := zap.NewNop()
erupeConfig := &_config.Config{ erupeConfig := &_config.Config{}
}
server := &Server{ server := &Server{
logger: logger, logger: logger,
@@ -145,7 +144,7 @@ func TestHandlePacketUnknownRequest(t *testing.T) {
logger: logger, logger: logger,
server: server, server: server,
rawConn: conn, rawConn: conn,
cryptConn: network.NewCryptConn(conn, _config.ZZ), cryptConn: network.NewCryptConn(conn, _config.ZZ, nil),
} }
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
@@ -176,7 +175,7 @@ func TestHandlePacketWithDevModeLogging(t *testing.T) {
logger: logger, logger: logger,
server: server, server: server,
rawConn: conn, rawConn: conn,
cryptConn: network.NewCryptConn(conn, _config.ZZ), cryptConn: network.NewCryptConn(conn, _config.ZZ, nil),
} }
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
@@ -214,7 +213,7 @@ func TestHandlePacketRequestTypes(t *testing.T) {
logger: logger, logger: logger,
server: server, server: server,
rawConn: conn, rawConn: conn,
cryptConn: network.NewCryptConn(conn, _config.ZZ), cryptConn: network.NewCryptConn(conn, _config.ZZ, nil),
} }
bf := byteframe.NewByteFrame() bf := byteframe.NewByteFrame()
@@ -324,7 +323,7 @@ func TestMockConnDeadlines(t *testing.T) {
func TestSessionWithCryptConn(t *testing.T) { func TestSessionWithCryptConn(t *testing.T) {
conn := newMockConn() conn := newMockConn()
cryptConn := network.NewCryptConn(conn, _config.ZZ) cryptConn := network.NewCryptConn(conn, _config.ZZ, nil)
if cryptConn == nil { if cryptConn == nil {
t.Fatal("NewCryptConn() returned nil") t.Fatal("NewCryptConn() returned nil")
@@ -361,7 +360,7 @@ func TestSessionWorkWithDevModeLogging(t *testing.T) {
logger: logger, logger: logger,
server: server, server: server,
rawConn: serverConn, rawConn: serverConn,
cryptConn: network.NewCryptConn(serverConn, _config.ZZ), cryptConn: network.NewCryptConn(serverConn, _config.ZZ, nil),
} }
_ = clientConn.Close() _ = clientConn.Close()
@@ -371,8 +370,7 @@ func TestSessionWorkWithDevModeLogging(t *testing.T) {
func TestSessionWorkWithEmptyRead(t *testing.T) { func TestSessionWorkWithEmptyRead(t *testing.T) {
logger := zap.NewNop() logger := zap.NewNop()
erupeConfig := &_config.Config{ erupeConfig := &_config.Config{}
}
server := &Server{ server := &Server{
logger: logger, logger: logger,
@@ -386,7 +384,7 @@ func TestSessionWorkWithEmptyRead(t *testing.T) {
logger: logger, logger: logger,
server: server, server: server,
rawConn: serverConn, rawConn: serverConn,
cryptConn: network.NewCryptConn(serverConn, _config.ZZ), cryptConn: network.NewCryptConn(serverConn, _config.ZZ, nil),
} }
_ = clientConn.Close() _ = clientConn.Close()

View File

@@ -101,7 +101,7 @@ func (s *Server) handleConnection(conn net.Conn) {
logger: s.logger, logger: s.logger,
server: s, server: s,
rawConn: conn, rawConn: conn,
cryptConn: network.NewCryptConn(conn, s.erupeConfig.RealClientMode), cryptConn: network.NewCryptConn(conn, s.erupeConfig.RealClientMode, s.logger),
} }
// Do the session's work. // Do the session's work.