diff --git a/game_list.tsv b/game_list.tsv index 4e61da1..98af24e 100644 --- a/game_list.tsv +++ b/game_list.tsv @@ -4312,7 +4312,7 @@ UFO Afterlight ufoafter UFO Extraterrestrials UFOextraterrestria UNO uno 299 MZIq0w UNO (DSiWare) unodsi 2669 w2G3ae -UNO (WiiWare) unowii 2630 2hUZSq +UNO (WiiWare) unowii 2630 2hUZSq 3 EbMKQdTKyYVwnaJudlXm URU: Ages Beyond MYST URUagesbeyondMYST Ubisoft Development ubisoftdev 1674 K4wfax Ubisoft Development Automatch ubisoftdevam 1675 K4wfax diff --git a/gamestats/main.go b/gamestats/main.go index 55cd25d..9215bf4 100644 --- a/gamestats/main.go +++ b/gamestats/main.go @@ -13,6 +13,8 @@ var ( pool *pgxpool.Pool serverName string + webSalt string + webHashPad string ) func StartServer() { @@ -20,6 +22,8 @@ func StartServer() { config := common.GetConfig() serverName = config.ServerName + webSalt = common.RandomString(32) + webHashPad = common.RandomString(8) common.ReadGameList() diff --git a/gamestats/http.go b/gamestats/web.go similarity index 57% rename from gamestats/http.go rename to gamestats/web.go index a3cbad6..bbccb43 100644 --- a/gamestats/http.go +++ b/gamestats/web.go @@ -2,7 +2,9 @@ package gamestats import ( "crypto/sha1" + "crypto/sha256" "encoding/base64" + "encoding/binary" "encoding/hex" "net/http" "net/url" @@ -14,7 +16,7 @@ import ( "github.com/logrusorgru/aurora/v3" ) -func HandleHTTPRequest(w http.ResponseWriter, r *http.Request) { +func HandleWebRequest(w http.ResponseWriter, r *http.Request) { logging.Info("GSTATS", aurora.Yellow(r.Method), aurora.Cyan(r.URL), "via", aurora.Cyan(r.Host), "from", aurora.BrightCyan(r.RemoteAddr)) u, err := url.Parse(r.URL.String()) @@ -48,24 +50,45 @@ func HandleHTTPRequest(w http.ResponseWriter, r *http.Request) { return } + var response []byte + hash := query.Get("hash") - var data string + token := calculateToken(r.URL, r.Host) if hash == "" { // No hash, just return token - data = common.RandomString(32) + response = []byte(token) } else { - // TODO: Handle subPath to get data here - common.UNUSED(subPath) - data = "" + // Check hash supplied by client + hasher := sha1.New() + hasher.Write([]byte(game.GameStatsKey)) + hasher.Write([]byte(token)) + expectedHash := hex.EncodeToString(hasher.Sum(nil)) + + if hash != expectedHash { + logging.Error("GSTATS", "Invalid hash") + replyHTTPError(w, http.StatusUnauthorized, "401 Unauthorized") + return + } + + switch subPath { + case "/web/client/get2.asp": + response = handleGet2(game, query) + + default: + logging.Warn("GSTATS", "Unhandled path:", aurora.Cyan(subPath)) + } + + // Padding to appease DWC + response = append(response, make([]byte, 13)...) if game.GameStatsVersion > 1 { // SHA-1 hash GamestatsKey + base64(data) + GameStatsKey - hashData := game.GameStatsKey + base64.URLEncoding.EncodeToString([]byte(data)) + game.GameStatsKey + hashData := game.GameStatsKey + base64.URLEncoding.EncodeToString([]byte(response)) + game.GameStatsKey hasher := sha1.New() hasher.Write([]byte(hashData)) // Append the hash sum as a hex string - data += hex.EncodeToString(hasher.Sum(nil)) + response = append(response, []byte(hex.EncodeToString(hasher.Sum(nil)))...) } } @@ -73,9 +96,27 @@ func HandleHTTPRequest(w http.ResponseWriter, r *http.Request) { w.Header().Set("Server", "Microsoft-IIS/6.0") w.Header().Add("Server", "GSTPRDSTATSWEB2") w.Header().Set("X-Powered-By", "ASP.NET") - w.Header().Set("Content-Length", strconv.Itoa(len(data))) + w.Header().Set("Content-Length", strconv.Itoa(len(response))) w.WriteHeader(200) - w.Write([]byte(data)) + w.Write(response) +} + +func calculateToken(u *url.URL, host string) string { + newURL := *u + newURL.RawQuery = url.Values{ + "pid": {u.Query().Get("pid")}, + }.Encode() + + hasher := sha256.New() + hasher.Write([]byte(host + newURL.String())) + hasher.Write([]byte(webSalt)) + return base64.URLEncoding.EncodeToString(hasher.Sum(nil))[:32] +} + +func handleGet2(game *common.GameInfo, query url.Values) []byte { + data := binary.LittleEndian.AppendUint32([]byte{}, 1) // RNK_GET + data = binary.LittleEndian.AppendUint32(data, 0) // count + return data } func replyHTTPError(w http.ResponseWriter, errorCode int, errorString string) { diff --git a/nas/main.go b/nas/main.go index f7571ab..78f95d9 100644 --- a/nas/main.go +++ b/nas/main.go @@ -68,7 +68,7 @@ func handleRequest(w http.ResponseWriter, r *http.Request) { // Check for *.gamestats(2).gs.* or gamestats(2).gs.* if regexGamestatsHost.MatchString(r.Host) { // Redirect to the gamestats server - gamestats.HandleHTTPRequest(w, r) + gamestats.HandleWebRequest(w, r) return }