Calculate friend codes for other games

This commit is contained in:
mkwcat 2024-03-09 06:24:07 -05:00
parent 8ffcdcec5f
commit bad2ae2ed7
No known key found for this signature in database
GPG Key ID: 7A505679CE9E7AA9
8 changed files with 101 additions and 22 deletions

View File

@ -4,8 +4,70 @@ import (
"crypto/md5"
"encoding/binary"
"fmt"
"strings"
)
const (
fcCRC8 = iota
fcMD5 = iota
)
var crc8Table = func() [256]byte {
var table [256]byte
poly := byte(0x07)
for i := 0; i < 256; i++ {
crc := byte(i)
for j := 0; j < 8; j++ {
if crc&0x80 != 0 {
crc = (crc << 1) ^ poly
} else {
crc <<= 1
}
}
table[i] = crc
}
return table
}()
func crc8(data []byte) byte {
crc := byte(0)
for _, b := range data {
crc = crc8Table[crc^b]
}
return crc
}
func getCRCType(gameId string) (crcType byte, reverse bool) {
reverse = false
if strings.HasPrefix(gameId, "RSB") {
crcType = fcCRC8
return
}
if strings.HasPrefix(gameId, "HDM") || strings.HasPrefix(gameId, "WDM") {
crcType = fcCRC8
reverse = true
return
}
switch gameId[0] {
case 'R', 'S', 'H', 'W', 'X', 'Y':
crcType = fcMD5
default:
crcType = fcCRC8
}
return
}
func CalcFriendCode(pid uint32, gameId string) uint64 {
if pid == 0 {
return 0
@ -18,15 +80,29 @@ func CalcFriendCode(pid uint32, gameId string) uint64 {
buffer[6] = gameId[1]
buffer[7] = gameId[0]
crc, _ := getCRCType(gameId)
if crc == fcCRC8 {
return uint64(pid) | (uint64(crc8(buffer)&0x7f) << 32)
}
digest := md5.Sum(buffer)
return uint64(pid) | (uint64(digest[0]&0xfe) << 31)
}
func CalcFriendCodeString(pid uint32, gameId string) string {
return GetRawFriendCodeString(CalcFriendCode(pid, gameId))
_, reverse := getCRCType(gameId)
return GetRawFriendCodeString(CalcFriendCode(pid, gameId), reverse)
}
func GetRawFriendCodeString(fc uint64) string {
s := fmt.Sprintf("%012d", fc)
func GetRawFriendCodeString(fc uint64, reverse bool) string {
s := fmt.Sprintf("%012d", max(min(fc, 999999999999), 0))
if reverse {
// Reverse the digit order
s = s[11:12] + s[10:11] + s[9:10] + s[8:9] + s[7:8] + s[6:7] + s[5:6] + s[4:5] + s[3:4] + s[2:3] + s[1:2] + s[0:1]
}
return s[len(s)-12:len(s)-8] + "-" + s[len(s)-8:len(s)-4] + "-" + s[len(s)-4:]
}

View File

@ -84,7 +84,6 @@ func (g *GameStatsSession) authp(command common.GameSpyCommand) {
}
g.ModuleName = "GSTATS:" + strconv.FormatInt(int64(g.User.ProfileId), 10)
g.ModuleName += "/" + common.CalcFriendCodeString(g.User.ProfileId, "RMCJ")
g.Authenticated = true
logging.Notice(g.ModuleName, "Authenticated, game name:", aurora.Cyan(g.GameInfo.Name))

View File

@ -82,20 +82,13 @@ func (g *GameSpySession) addFriend(command common.GameSpyCommand) {
return
}
// Required for a friend auth
if g.User.LastName == "" {
logging.Error(g.ModuleName, "Add friend without last name")
g.replyError(ErrAddFriendBadFrom)
return
}
if newProfileId == uint64(g.User.ProfileId) {
logging.Error(g.ModuleName, "Attempt to add self as friend")
g.replyError(ErrAddFriendBadNew)
return
}
fc := common.CalcFriendCodeString(uint32(newProfileId), "RMCJ")
fc := common.CalcFriendCodeString(uint32(newProfileId), g.User.GsbrCode[:4])
logging.Info(g.ModuleName, "Add friend:", aurora.Cyan(strNewProfileId), aurora.Cyan(fc))
if g.isFriendAuthorized(uint32(newProfileId)) {
@ -123,7 +116,7 @@ func (g *GameSpySession) addFriend(command common.GameSpyCommand) {
if newSession.GameName != g.GameName {
logging.Error(g.ModuleName, "Destination is not playing the same game")
g.replyError(ErrAddFriendBadNew)
// g.replyError(ErrAddFriendBadNew)
return
}

View File

@ -256,7 +256,7 @@ func (g *GameSpySession) login(command common.GameSpyCommand) {
}
g.ModuleName = "GPCM:" + strconv.FormatInt(int64(g.User.ProfileId), 10) + "*"
g.ModuleName += "/" + common.CalcFriendCodeString(g.User.ProfileId, "RMCJ") + "*"
g.ModuleName += "/" + common.CalcFriendCodeString(g.User.ProfileId, g.User.GsbrCode[:4]) + "*"
// Check to see if a session is already open with this profile ID
mutex.Lock()
@ -293,10 +293,10 @@ func (g *GameSpySession) login(command common.GameSpyCommand) {
g.DeviceAuthenticated = deviceAuth
g.LoggedIn = true
g.ModuleName = "GPCM:" + strconv.FormatInt(int64(g.User.ProfileId), 10)
g.ModuleName += "/" + common.CalcFriendCodeString(g.User.ProfileId, "RMCJ")
g.ModuleName += "/" + common.CalcFriendCodeString(g.User.ProfileId, g.User.GsbrCode[:4])
// Notify QR2 of the login
qr2.Login(g.User.ProfileId, gamecd, ingamesn, cfc, g.Conn.RemoteAddr().String(), g.NeedsExploit, g.DeviceAuthenticated, g.User.Restricted, KickPlayer)
qr2.Login(g.User.ProfileId, gamecd, ingamesn, cfc, g.User.GsbrCode[:4], g.Conn.RemoteAddr().String(), g.NeedsExploit, g.DeviceAuthenticated, g.User.Restricted, KickPlayer)
replyUserId := g.User.UserId
if g.UnitCode == UnitCodeDS {

View File

@ -220,6 +220,12 @@ func login(moduleName string, fields map[string]string, isLocalhost bool) map[st
return param
}
if len(gsbrcd) < 4 || strings.ContainsRune(gsbrcd, 0) {
logging.Error(moduleName, "Invalid gsbrcd string in form")
param["returncd"] = "103"
return param
}
lang, ok := fields["lang"]
if !ok {
lang = "ff"

View File

@ -596,14 +596,16 @@ func GetGroups(gameNames []string, groupNames []string, sorted bool) []GroupInfo
InGameName: rawPlayer["+ingamesn"],
}
pid, err := strconv.ParseUint(rawPlayer["dwc_pid"], 10, 32)
if err == nil {
if fcGame := rawPlayer["+fcgameid"]; len(fcGame) == 4 {
playerInfo.FriendCode = common.CalcFriendCodeString(uint32(pid), fcGame)
}
}
if rawPlayer["gamename"] == "mariokartwii" {
playerInfo.VersusELO = rawPlayer["ev"]
playerInfo.BattleELO = rawPlayer["eb"]
pid, err := strconv.ParseUint(rawPlayer["dwc_pid"], 10, 32)
if err == nil {
playerInfo.FriendCode = common.CalcFriendCodeString(uint32(pid), "RMCJ")
}
}
for i := 0; i < 32; i++ {

View File

@ -5,6 +5,7 @@ type LoginInfo struct {
GameCode string
InGameName string
ConsoleFriendCode uint64
FriendKeyGame string
GPPublicIP string
NeedsExploit bool
DeviceAuthenticated bool
@ -15,7 +16,7 @@ type LoginInfo struct {
var logins = map[uint32]*LoginInfo{}
func Login(profileID uint32, gameCode string, inGameName string, consoleFriendCode uint64, publicIP string, needsExploit bool, deviceAuthenticated bool, restricted bool, gpErrorCallback func(uint32, string)) {
func Login(profileID uint32, gameCode string, inGameName string, consoleFriendCode uint64, fcGame string, publicIP string, needsExploit bool, deviceAuthenticated bool, restricted bool, gpErrorCallback func(uint32, string)) {
mutex.Lock()
defer mutex.Unlock()
@ -24,6 +25,7 @@ func Login(profileID uint32, gameCode string, inGameName string, consoleFriendCo
GameCode: gameCode,
InGameName: inGameName,
ConsoleFriendCode: consoleFriendCode,
FriendKeyGame: fcGame,
GPPublicIP: publicIP,
NeedsExploit: needsExploit,
DeviceAuthenticated: deviceAuthenticated,

View File

@ -232,6 +232,7 @@ func (session *Session) setProfileID(moduleName string, newPID string, gpcmIP st
}
session.Data["+gppublicip"], _ = common.IPFormatToString(gpPublicIP)
session.Data["+fcgameid"] = loginInfo.FriendKeyGame
session.Data["dwc_pid"] = newPID
logging.Notice(moduleName, "Opened session with PID", aurora.Cyan(newPID))