mirror of
https://github.com/WiiLink24/wfc-server.git
synced 2026-03-21 17:44:58 -05:00
NAS: Check and sanitize payload ID
This commit is contained in:
parent
7c7691eed3
commit
81f219da4c
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,5 +1,6 @@
|
|||
# Local configuration file
|
||||
config.xml
|
||||
salt.bin
|
||||
|
||||
# Payload data
|
||||
payload
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ import (
|
|||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"github.com/logrusorgru/aurora/v3"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"wwfc/logging"
|
||||
)
|
||||
|
||||
func getStage1(r *Response, fields map[string]string) map[string]string {
|
||||
|
|
@ -27,56 +27,85 @@ func getStage1(r *Response, fields map[string]string) map[string]string {
|
|||
return map[string]string{}
|
||||
}
|
||||
|
||||
func handlePayloadRequest(w http.ResponseWriter, r *http.Request) {
|
||||
func handlePayloadRequest(moduleName string, w http.ResponseWriter, r *http.Request) {
|
||||
// Example request:
|
||||
// GET /payload?g=RMCPD00&s=4e44b095817f8cfb62e6cffd57e9cfd411004a492784039ea4b2b7ca64717c91&h=9fdb6f60
|
||||
|
||||
u, err := url.Parse(r.URL.String())
|
||||
if err != nil {
|
||||
log.Printf(aurora.Red("failed to parse URL").String())
|
||||
logging.Error(moduleName, "Failed to parse URL")
|
||||
return
|
||||
}
|
||||
|
||||
query, err := url.ParseQuery(u.RawQuery)
|
||||
if err != nil {
|
||||
log.Printf(aurora.Red("failed to parse URL query").String())
|
||||
logging.Error(moduleName, "Failed to parse URL query")
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Read payload ID (g) from URL
|
||||
dat, err := os.ReadFile("payload/binary/RMCPD00.bin")
|
||||
// Read payload ID (g) from URL
|
||||
game := query["g"][0]
|
||||
if len(game) != 7 && len(game) != 9 {
|
||||
logging.Error(moduleName, "Invalid or missing game ID:", aurora.Cyan(game))
|
||||
return
|
||||
}
|
||||
|
||||
if (len(game) == 7 && game[4] != 'D') || (len(game) == 9 && game[4] != 'N') {
|
||||
logging.Error(moduleName, "Invalid game ID:", aurora.Cyan(game))
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < 4; i++ {
|
||||
if (game[i] >= 'A' && game[i] <= 'Z') || (game[i] >= '0' && game[i] <= '9') {
|
||||
continue
|
||||
}
|
||||
|
||||
logging.Error(moduleName, "Invalid game ID char:", aurora.Cyan(game))
|
||||
return
|
||||
}
|
||||
|
||||
for i := 5; i < len(game); i++ {
|
||||
if (game[i] >= '0' && game[i] <= '9') || (game[i] >= 'a' && game[i] <= 'f') {
|
||||
continue
|
||||
}
|
||||
|
||||
logging.Error(moduleName, "Invalid game ID version:", aurora.Cyan(game))
|
||||
return
|
||||
}
|
||||
|
||||
dat, err := os.ReadFile("payload/binary/payload." + game + ".bin")
|
||||
if err != nil {
|
||||
log.Printf(aurora.Red("failed to read payload file").String())
|
||||
logging.Error(moduleName, "Failed to read payload file")
|
||||
return
|
||||
}
|
||||
|
||||
salt, ok := query["s"]
|
||||
if ok {
|
||||
if len(salt[0]) != 64 {
|
||||
log.Printf(aurora.Red("invalid salt length").String())
|
||||
logging.Error(moduleName, "Invalid salt length:", aurora.BrightCyan(len(salt[0])))
|
||||
return
|
||||
}
|
||||
|
||||
_, err := hex.DecodeString(salt[0])
|
||||
if err != nil {
|
||||
log.Printf(aurora.Red("invalid salt hex string").String())
|
||||
logging.Error(moduleName, "Invalid salt hex string")
|
||||
return
|
||||
}
|
||||
|
||||
saltHashTest, ok := query["h"]
|
||||
if !ok {
|
||||
log.Printf(aurora.Red("Request is missing salt hash").String())
|
||||
logging.Error(moduleName, "Request is missing salt hash")
|
||||
return
|
||||
}
|
||||
|
||||
if len(saltHashTest[0]) != 8 {
|
||||
log.Printf(aurora.Red("Invalid salt hash length").String())
|
||||
logging.Error(moduleName, "Invalid salt hash length:", aurora.BrightCyan(len(saltHashTest[0])))
|
||||
return
|
||||
}
|
||||
|
||||
saltHashTestData, err := hex.DecodeString(saltHashTest[0])
|
||||
if err != nil {
|
||||
log.Printf(aurora.Red("Invalid salt hash hex string").String())
|
||||
logging.Error(moduleName, "Invalid salt hash hex string")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +120,7 @@ func handlePayloadRequest(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
saltHash := hashCtx.Sum(nil)
|
||||
if !bytes.Equal(saltHashTestData, saltHash[:4]) {
|
||||
log.Printf(aurora.Red("Invalid salt hash").String())
|
||||
logging.Error(moduleName, "Salt hash mismatch")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +129,7 @@ func handlePayloadRequest(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// TODO: Cache the request for a zero salt
|
||||
|
||||
rsaData, err := os.ReadFile("payload/stage1-private-temp.pem")
|
||||
rsaData, err := os.ReadFile("payload/private-key.pem")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
@ -113,7 +142,7 @@ func handlePayloadRequest(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
rsaKey, ok := parsedKey.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
log.Fatalf("got unexpected key type: %T", parsedKey)
|
||||
panic("Unexpected key type")
|
||||
}
|
||||
|
||||
// Hash our data then sign
|
||||
|
|
@ -133,7 +162,6 @@ func handlePayloadRequest(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
dat = append(append(dat[:0x10], signature...), dat[0x110:]...)
|
||||
|
||||
log.Printf(aurora.White("write data").String())
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(dat)))
|
||||
w.Write(dat)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ func (route *Route) Handle() http.Handler {
|
|||
// TODO: Move this to its own server
|
||||
// Check for /payload
|
||||
if strings.HasPrefix(r.URL.String(), "/payload") {
|
||||
handlePayloadRequest(w, r)
|
||||
handlePayloadRequest(moduleName, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user