GameStats: Handle /web/client/get2.asp

This commit is contained in:
mkwcat 2024-02-05 22:43:35 -05:00
parent 51ca27fb1e
commit 496f918f7f
No known key found for this signature in database
GPG Key ID: 7A505679CE9E7AA9
4 changed files with 57 additions and 12 deletions

View File

@ -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

1 1001 Minigolf Challenge 1001MinigolfChalle
4312 UFO Extraterrestrials UFOextraterrestria
4313 UNO uno 299 MZIq0w
4314 UNO (DSiWare) unodsi 2669 w2G3ae
4315 UNO (WiiWare) unowii 2630 2hUZSq 3 EbMKQdTKyYVwnaJudlXm
4316 URU: Ages Beyond MYST URUagesbeyondMYST
4317 Ubisoft Development ubisoftdev 1674 K4wfax
4318 Ubisoft Development Automatch ubisoftdevam 1675 K4wfax

View File

@ -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()

View File

@ -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) {

View File

@ -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
}