mirror of
https://github.com/WiiLink24/wfc-server.git
synced 2026-04-19 15:57:33 -05:00
NAS: Handle /p0 and /payload requests
This commit is contained in:
parent
91f3d0b06c
commit
4839bc0a00
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -1 +1,5 @@
|
|||
# Local configuration file
|
||||
config.xml
|
||||
|
||||
# Payload data
|
||||
payload
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ func StartServer() {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
// Finally, initialize the HTTP server
|
||||
address := config.Address + ":" + config.Port
|
||||
r := NewRoute()
|
||||
ac := r.HandleGroup("ac")
|
||||
|
|
@ -40,6 +39,13 @@ func StartServer() {
|
|||
ac.HandleAction("login", login)
|
||||
}
|
||||
|
||||
// TODO: Hack lol
|
||||
p0 := r.HandleGroup("p0")
|
||||
{
|
||||
p0.HandleAction("acctcreate", getStage1)
|
||||
p0.HandleAction("login", getStage1)
|
||||
}
|
||||
|
||||
logging.Notice("NAS", "Starting HTTP server on", address)
|
||||
log.Fatal(nhttp.ListenAndServe(address, r.Handle()))
|
||||
}
|
||||
|
|
|
|||
104
nas/payload.go
Normal file
104
nas/payload.go
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package nas
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"github.com/logrusorgru/aurora/v3"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func getStage1(r *Response, fields map[string]string) map[string]string {
|
||||
dat, err := os.ReadFile("payload/stage1.bin")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
r.payload = dat
|
||||
return map[string]string{}
|
||||
}
|
||||
|
||||
func handlePayloadRequest(w http.ResponseWriter, r *http.Request) {
|
||||
// Example request:
|
||||
// GET /payload?g=RMCPD00&s=30f75b5ec08c159cb66493d5ae889090012a87d8a113696704ade9b610f6f33c
|
||||
|
||||
u, err := url.Parse(r.URL.String())
|
||||
if err != nil {
|
||||
log.Printf(aurora.Red("failed to parse URL").String())
|
||||
return
|
||||
}
|
||||
|
||||
query, err := url.ParseQuery(u.RawQuery)
|
||||
if err != nil {
|
||||
log.Printf(aurora.Red("failed to parse URL query").String())
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Read payload ID (g) from URL
|
||||
dat, err := os.ReadFile("payload/binary/RMCPD00.bin")
|
||||
if err != nil {
|
||||
log.Printf(aurora.Red("failed to read payload file").String())
|
||||
return
|
||||
}
|
||||
|
||||
salt, ok := query["s"]
|
||||
if ok {
|
||||
if len(salt[0]) != 64 {
|
||||
log.Printf(aurora.Red("invalid salt length").String())
|
||||
return
|
||||
}
|
||||
|
||||
salt_data, err := hex.DecodeString(salt[0])
|
||||
if err != nil {
|
||||
log.Printf(aurora.Red("invalid salt hex string").String())
|
||||
return
|
||||
}
|
||||
|
||||
dat = append(append(dat[:0x110], salt_data...), dat[0x130:]...)
|
||||
}
|
||||
|
||||
rsaData, err := os.ReadFile("payload/stage1-private-temp.pem")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
rsaBlock, _ := pem.Decode(rsaData)
|
||||
parsedKey, err := x509.ParsePKCS8PrivateKey(rsaBlock.Bytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
rsaKey, ok := parsedKey.(*rsa.PrivateKey)
|
||||
if !ok {
|
||||
log.Fatalf("got unexpected key type: %T", parsedKey)
|
||||
}
|
||||
|
||||
// Hash our data then sign
|
||||
hash := sha256.New()
|
||||
_, err = hash.Write(dat[0x110:])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
contentsHashSum := hash.Sum(nil)
|
||||
|
||||
reader := rand.Reader
|
||||
signature, err := rsa.SignPKCS1v15(reader, rsaKey, crypto.SHA256, contentsHashSum)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
10
nas/route.go
10
nas/route.go
|
|
@ -55,6 +55,7 @@ var (
|
|||
|
||||
func (route *Route) Handle() http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// TODO: Move this to its own server
|
||||
// Check for *.sake.gs.* or sake.gs.*
|
||||
if regexSakeURL.MatchString(r.Host) {
|
||||
// Redirect to the sake server
|
||||
|
|
@ -65,6 +66,13 @@ func (route *Route) Handle() http.Handler {
|
|||
logging.Notice("NAS", aurora.Yellow(r.Method), aurora.Cyan(r.URL), "via", aurora.Cyan(r.Host), "from", aurora.BrightCyan(r.RemoteAddr))
|
||||
moduleName := "NAS:" + r.RemoteAddr
|
||||
|
||||
// TODO: Move this to its own server
|
||||
// Check for /payload
|
||||
if strings.HasPrefix(r.URL.String(), "/payload") {
|
||||
handlePayloadRequest(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
logging.Error(moduleName, "Failed to parse form")
|
||||
|
|
@ -123,6 +131,8 @@ func (route *Route) Handle() http.Handler {
|
|||
}
|
||||
response.payload = []byte(param.Encode())
|
||||
response.payload = []byte(strings.Replace(string(response.payload), "%2A", "*", -1))
|
||||
// DWC treats the response like a null terminated string
|
||||
response.payload = append(response.payload, 0x00)
|
||||
}
|
||||
|
||||
w.Header().Set("NODE", "wifiappe1")
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user