mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
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:
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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")
|
||||||
}
|
}
|
||||||
@@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -44,4 +44,3 @@ func NewTestConfig() *_config.Config {
|
|||||||
HideLoginNotice: false,
|
HideLoginNotice: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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:])
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user