mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Add CI security suite and scrub hardcoded local host/path defaults
This commit is contained in:
parent
550366df07
commit
00086c2ad9
5 changed files with 163 additions and 26 deletions
137
.github/workflows/security.yml
vendored
Normal file
137
.github/workflows/security.yml
vendored
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
name: Security
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
pull_request:
|
||||||
|
branches: [master]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
codeql:
|
||||||
|
name: CodeQL (C/C++)
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y \
|
||||||
|
cmake \
|
||||||
|
build-essential \
|
||||||
|
pkg-config \
|
||||||
|
libsdl2-dev \
|
||||||
|
libglew-dev \
|
||||||
|
libglm-dev \
|
||||||
|
libssl-dev \
|
||||||
|
zlib1g-dev \
|
||||||
|
libavformat-dev \
|
||||||
|
libavcodec-dev \
|
||||||
|
libswscale-dev \
|
||||||
|
libavutil-dev \
|
||||||
|
libunicorn-dev \
|
||||||
|
libx11-dev
|
||||||
|
sudo apt-get install -y libstormlib-dev || true
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v3
|
||||||
|
with:
|
||||||
|
languages: cpp
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
||||||
|
cmake --build build --parallel $(nproc)
|
||||||
|
|
||||||
|
- name: Analyze
|
||||||
|
uses: github/codeql-action/analyze@v3
|
||||||
|
|
||||||
|
semgrep:
|
||||||
|
name: Semgrep
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.x"
|
||||||
|
|
||||||
|
- name: Install Semgrep
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install semgrep
|
||||||
|
|
||||||
|
- name: Run Semgrep (security + secrets)
|
||||||
|
run: |
|
||||||
|
semgrep scan \
|
||||||
|
--config p/security-audit \
|
||||||
|
--config p/secrets \
|
||||||
|
--error
|
||||||
|
|
||||||
|
sanitizer-build:
|
||||||
|
name: Sanitizer Build (ASan/UBSan)
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y \
|
||||||
|
cmake \
|
||||||
|
build-essential \
|
||||||
|
pkg-config \
|
||||||
|
libsdl2-dev \
|
||||||
|
libglew-dev \
|
||||||
|
libglm-dev \
|
||||||
|
libssl-dev \
|
||||||
|
zlib1g-dev \
|
||||||
|
libavformat-dev \
|
||||||
|
libavcodec-dev \
|
||||||
|
libswscale-dev \
|
||||||
|
libavutil-dev \
|
||||||
|
libunicorn-dev \
|
||||||
|
libx11-dev
|
||||||
|
sudo apt-get install -y libstormlib-dev || true
|
||||||
|
|
||||||
|
- name: Configure (ASan/UBSan)
|
||||||
|
run: |
|
||||||
|
cmake -S . -B build \
|
||||||
|
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
|
||||||
|
-DWOWEE_BUILD_TESTS=ON \
|
||||||
|
-DCMAKE_C_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer" \
|
||||||
|
-DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer" \
|
||||||
|
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined" \
|
||||||
|
-DCMAKE_SHARED_LINKER_FLAGS="-fsanitize=address,undefined"
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build build --parallel $(nproc)
|
||||||
|
|
||||||
|
- name: Run tests (if present)
|
||||||
|
env:
|
||||||
|
ASAN_OPTIONS: detect_leaks=1:halt_on_error=1
|
||||||
|
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
|
||||||
|
run: |
|
||||||
|
if [ -f build/CTestTestfile.cmake ] || [ -d build/tests ]; then
|
||||||
|
ctest --test-dir build --output-on-failure
|
||||||
|
else
|
||||||
|
echo "No tests configured; sanitizer build completed."
|
||||||
|
fi
|
||||||
|
|
@ -286,7 +286,7 @@ std::string host = realm.address.substr(0, colonPos);
|
||||||
uint16_t port = std::stoi(realm.address.substr(colonPos + 1));
|
uint16_t port = std::stoi(realm.address.substr(colonPos + 1));
|
||||||
```
|
```
|
||||||
|
|
||||||
**Realm address format:** `"127.0.0.1:8085"`
|
**Realm address format:** `"localhost:8085"`
|
||||||
|
|
||||||
### Phase 3: World Server Connection
|
### Phase 3: World Server Connection
|
||||||
|
|
||||||
|
|
@ -295,7 +295,7 @@ uint16_t port = std::stoi(realm.address.substr(colonPos + 1));
|
||||||
```cpp
|
```cpp
|
||||||
game::GameHandler gameHandler;
|
game::GameHandler gameHandler;
|
||||||
gameHandler.connect(
|
gameHandler.connect(
|
||||||
host, // e.g., "127.0.0.1"
|
host, // e.g., "localhost"
|
||||||
port, // e.g., 8085
|
port, // e.g., 8085
|
||||||
sessionKey, // 40 bytes from auth server
|
sessionKey, // 40 bytes from auth server
|
||||||
accountName, // Same account
|
accountName, // Same account
|
||||||
|
|
@ -447,7 +447,7 @@ void testCompleteAuthFlow() {
|
||||||
|
|
||||||
// Real auth handler
|
// Real auth handler
|
||||||
auth::AuthHandler auth;
|
auth::AuthHandler auth;
|
||||||
auth.connect("127.0.0.1", 3724);
|
auth.connect("localhost", 3724);
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
std::vector<uint8_t> key;
|
std::vector<uint8_t> key;
|
||||||
|
|
@ -472,7 +472,7 @@ void testCompleteAuthFlow() {
|
||||||
MockWorldServer worldServer(8085);
|
MockWorldServer worldServer(8085);
|
||||||
|
|
||||||
game::GameHandler game;
|
game::GameHandler game;
|
||||||
game.connect("127.0.0.1", 8085, key, "TEST", 12340);
|
game.connect("localhost", 8085, key, "TEST", 12340);
|
||||||
|
|
||||||
bool worldSuccess = false;
|
bool worldSuccess = false;
|
||||||
game.setOnSuccess([&worldSuccess]() {
|
game.setOnSuccess([&worldSuccess]() {
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ struct Realm {
|
||||||
uint8_t lock; // Lock status
|
uint8_t lock; // Lock status
|
||||||
uint8_t flags; // Realm flags (bit 0x04 = has version info)
|
uint8_t flags; // Realm flags (bit 0x04 = has version info)
|
||||||
std::string name; // Realm name (e.g., "My Private Server")
|
std::string name; // Realm name (e.g., "My Private Server")
|
||||||
std::string address; // Server address (e.g., "127.0.0.1:8085")
|
std::string address; // Server address (e.g., "localhost:8085")
|
||||||
float population; // Population level (0.0 to 2.0+)
|
float population; // Population level (0.0 to 2.0+)
|
||||||
uint8_t characters; // Number of characters player has on this realm
|
uint8_t characters; // Number of characters player has on this realm
|
||||||
uint8_t timezone; // Timezone ID
|
uint8_t timezone; // Timezone ID
|
||||||
|
|
@ -127,7 +127,7 @@ int main() {
|
||||||
|
|
||||||
// Connect
|
// Connect
|
||||||
std::cout << "Connecting to authentication server..." << std::endl;
|
std::cout << "Connecting to authentication server..." << std::endl;
|
||||||
if (!auth.connect("127.0.0.1", 3724)) {
|
if (!auth.connect("localhost", 3724)) {
|
||||||
std::cerr << "Connection failed" << std::endl;
|
std::cerr << "Connection failed" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -218,7 +218,7 @@ int main() {
|
||||||
std::cout << "Address: " << selectedRealm.address << std::endl;
|
std::cout << "Address: " << selectedRealm.address << std::endl;
|
||||||
|
|
||||||
// TODO: Parse address and connect to world server
|
// TODO: Parse address and connect to world server
|
||||||
// Example: "127.0.0.1:8085" -> host="127.0.0.1", port=8085
|
// Example: "localhost:8085" -> host="localhost", port=8085
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -424,7 +424,7 @@ For testing without a live server, you can create mock realms:
|
||||||
Realm mockRealm;
|
Realm mockRealm;
|
||||||
mockRealm.id = 1;
|
mockRealm.id = 1;
|
||||||
mockRealm.name = "Test Realm";
|
mockRealm.name = "Test Realm";
|
||||||
mockRealm.address = "127.0.0.1:8085";
|
mockRealm.address = "localhost:8085";
|
||||||
mockRealm.icon = 1;
|
mockRealm.icon = 1;
|
||||||
mockRealm.lock = 0;
|
mockRealm.lock = 0;
|
||||||
mockRealm.flags = 0x04; // Has version info
|
mockRealm.flags = 0x04; // Has version info
|
||||||
|
|
@ -438,7 +438,7 @@ mockRealm.build = 12340;
|
||||||
|
|
||||||
// Test parsing address
|
// Test parsing address
|
||||||
std::string host = parseHost(mockRealm.address);
|
std::string host = parseHost(mockRealm.address);
|
||||||
assert(host == "127.0.0.1");
|
assert(host == "localhost");
|
||||||
|
|
||||||
uint16_t port = parsePort(mockRealm.address);
|
uint16_t port = parsePort(mockRealm.address);
|
||||||
assert(port == 8085);
|
assert(port == 8085);
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ The authentication screen comes with local server defaults:
|
||||||
|
|
||||||
| Setting | Default Value | Description |
|
| Setting | Default Value | Description |
|
||||||
|---------|---------------|-------------|
|
|---------|---------------|-------------|
|
||||||
| **Hostname** | 127.0.0.1 | Localhost (your machine) |
|
| **Hostname** | localhost | Localhost (your machine) |
|
||||||
| **Port** | 3724 | Standard auth server port |
|
| **Port** | 3724 | Standard auth server port |
|
||||||
| **Username** | (empty) | Your account username |
|
| **Username** | (empty) | Your account username |
|
||||||
| **Password** | (empty) | Your account password |
|
| **Password** | (empty) | Your account password |
|
||||||
|
|
@ -120,16 +120,16 @@ nano authserver.conf
|
||||||
|
|
||||||
**Key settings in `authserver.conf`:**
|
**Key settings in `authserver.conf`:**
|
||||||
```ini
|
```ini
|
||||||
LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth"
|
LoginDatabaseInfo = "localhost;3306;trinity;trinity;auth"
|
||||||
RealmServerPort = 3724
|
RealmServerPort = 3724
|
||||||
BindIP = "127.0.0.1"
|
BindIP = "localhost"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Key settings in `worldserver.conf`:**
|
**Key settings in `worldserver.conf`:**
|
||||||
```ini
|
```ini
|
||||||
LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth"
|
LoginDatabaseInfo = "localhost;3306;trinity;trinity;auth"
|
||||||
WorldDatabaseInfo = "127.0.0.1;3306;trinity;trinity;world"
|
WorldDatabaseInfo = "localhost;3306;trinity;trinity;world"
|
||||||
CharacterDatabaseInfo = "127.0.0.1;3306;trinity;trinity;characters"
|
CharacterDatabaseInfo = "localhost;3306;trinity;trinity;characters"
|
||||||
|
|
||||||
DataDir = "/path/to/your/WoW-3.3.5a/Data" # Your WoW client data directory
|
DataDir = "/path/to/your/WoW-3.3.5a/Data" # Your WoW client data directory
|
||||||
```
|
```
|
||||||
|
|
@ -154,7 +154,7 @@ account set gmlevel testuser 3 -1
|
||||||
|
|
||||||
In the worldserver console:
|
In the worldserver console:
|
||||||
```
|
```
|
||||||
realm add "Local Test Realm" 127.0.0.1:8085 0 1
|
realm add "Local Test Realm" localhost:8085 0 1
|
||||||
```
|
```
|
||||||
|
|
||||||
Or directly in database:
|
Or directly in database:
|
||||||
|
|
@ -162,7 +162,7 @@ Or directly in database:
|
||||||
mysql -u trinity -ptrinity auth
|
mysql -u trinity -ptrinity auth
|
||||||
|
|
||||||
INSERT INTO realmlist (name, address, port, icon, realmflags, timezone, allowedSecurityLevel)
|
INSERT INTO realmlist (name, address, port, icon, realmflags, timezone, allowedSecurityLevel)
|
||||||
VALUES ('Local Test Realm', '127.0.0.1', 8085, 1, 0, 1, 0);
|
VALUES ('Local Test Realm', 'localhost', 8085, 1, 0, 1, 0);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Running the Server
|
## Running the Server
|
||||||
|
|
@ -212,14 +212,14 @@ server shutdown 10 # Shutdown in 10 seconds
|
||||||
### 1. Start the Client
|
### 1. Start the Client
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /home/k/Desktop/wowee/wowee
|
cd /path/to/wowee
|
||||||
./build/bin/wowee
|
./build/bin/wowee
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Login Screen
|
### 2. Login Screen
|
||||||
|
|
||||||
You'll see the authentication screen with default values:
|
You'll see the authentication screen with default values:
|
||||||
- **Hostname:** 127.0.0.1 (already set)
|
- **Hostname:** localhost (already set)
|
||||||
- **Port:** 3724 (already set)
|
- **Port:** 3724 (already set)
|
||||||
- **Username:** (enter your account username)
|
- **Username:** (enter your account username)
|
||||||
- **Password:** (enter your account password)
|
- **Password:** (enter your account password)
|
||||||
|
|
@ -291,7 +291,7 @@ ps aux | grep worldserver
|
||||||
netstat -an | grep 8085
|
netstat -an | grep 8085
|
||||||
|
|
||||||
# Update realmlist address
|
# Update realmlist address
|
||||||
UPDATE realmlist SET address='127.0.0.1' WHERE id=1;
|
UPDATE realmlist SET address='localhost' WHERE id=1;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Cannot Enter World
|
### Cannot Enter World
|
||||||
|
|
@ -335,13 +335,13 @@ ifconfig | grep inet
|
||||||
|
|
||||||
Edit `authserver.conf`:
|
Edit `authserver.conf`:
|
||||||
```ini
|
```ini
|
||||||
BindIP = "0.0.0.0" # Listen on all interfaces
|
BindIP = "<bind-address>" # Listen on all interfaces
|
||||||
```
|
```
|
||||||
|
|
||||||
Edit database:
|
Edit database:
|
||||||
```sql
|
```sql
|
||||||
mysql -u trinity -ptrinity auth
|
mysql -u trinity -ptrinity auth
|
||||||
UPDATE realmlist SET address='192.168.1.100' WHERE id=1; # Your local IP
|
UPDATE realmlist SET address='<your-lan-ip>' WHERE id=1; # Your local IP
|
||||||
```
|
```
|
||||||
|
|
||||||
**3. Configure firewall:**
|
**3. Configure firewall:**
|
||||||
|
|
@ -351,7 +351,7 @@ sudo ufw allow 8085 # World server
|
||||||
```
|
```
|
||||||
|
|
||||||
**4. In wowee:**
|
**4. In wowee:**
|
||||||
- Change hostname to your server's local IP (e.g., 192.168.1.100)
|
- Change hostname to your server's local IP (e.g., <your-lan-ip>)
|
||||||
- Keep port as 3724
|
- Keep port as 3724
|
||||||
- Connect
|
- Connect
|
||||||
|
|
||||||
|
|
@ -366,7 +366,7 @@ For testing with a remote server (VPS, dedicated server):
|
||||||
**Server configuration:**
|
**Server configuration:**
|
||||||
```ini
|
```ini
|
||||||
# authserver.conf
|
# authserver.conf
|
||||||
BindIP = "0.0.0.0"
|
BindIP = "<bind-address>"
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
UPDATE realmlist SET address='your.server.ip' WHERE id=1;
|
UPDATE realmlist SET address='your.server.ip' WHERE id=1;
|
||||||
|
|
@ -600,7 +600,7 @@ server shutdown 10
|
||||||
- [ ] Account created with proper credentials
|
- [ ] Account created with proper credentials
|
||||||
- [ ] Firewall allows ports 3724 and 8085
|
- [ ] Firewall allows ports 3724 and 8085
|
||||||
- [ ] WOW_DATA_PATH set correctly (if using MPQ assets)
|
- [ ] WOW_DATA_PATH set correctly (if using MPQ assets)
|
||||||
- [ ] Client can resolve hostname (127.0.0.1 for localhost)
|
- [ ] Client can resolve hostname (localhost for localhost)
|
||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
// UI state
|
// UI state
|
||||||
char hostname[256] = "127.0.0.1";
|
char hostname[256] = "localhost";
|
||||||
char username[256] = "";
|
char username[256] = "";
|
||||||
char password[256] = "";
|
char password[256] = "";
|
||||||
char pinCode[32] = "";
|
char pinCode[32] = "";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue