mirror of
https://github.com/WiiLink24/wfc-server.git
synced 2026-09-15 03:55:56 -05:00
QR2/GPCM: Add protection for restricted players joining public rooms
This commit is contained in:
@@ -478,6 +478,26 @@ func (g *GameSpySession) bestieMessage(command common.GameSpyCommand) {
|
||||
return
|
||||
}
|
||||
|
||||
if g.User.Restricted || toSession.User.Restricted {
|
||||
// Check with QR2 if the room is public or private
|
||||
resvError := qr2.CheckGPReservationAllowed(g.QR2IP, g.User.ProfileId, uint32(toProfileId), msgMatchData.Reservation.MatchType)
|
||||
if resvError != "ok" {
|
||||
if resvError == "restricted" || resvError == "restricted_join" {
|
||||
logging.Error(g.ModuleName, "RESERVATION: Restricted user tried to connect to public room")
|
||||
|
||||
// Kick the player(s)
|
||||
if g.User.Restricted {
|
||||
kickPlayer(toSession.User.ProfileId, resvError)
|
||||
}
|
||||
if toSession.User.Restricted {
|
||||
kickPlayer(g.User.ProfileId, resvError)
|
||||
}
|
||||
}
|
||||
// Otherwise generic error?
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !sameAddress {
|
||||
searchId := qr2.GetSearchID(g.QR2IP)
|
||||
msgMatchData.Reservation.PublicIP = uint32(searchId & 0xffffffff)
|
||||
|
||||
12
gpcm/kick.go
12
gpcm/kick.go
@@ -1,9 +1,6 @@
|
||||
package gpcm
|
||||
|
||||
func KickPlayer(profileID uint32, reason string) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
func kickPlayer(profileID uint32, reason string) {
|
||||
if session, exists := sessions[profileID]; exists {
|
||||
errorMessage := WWFCMsgKickedGeneric
|
||||
|
||||
@@ -33,3 +30,10 @@ func KickPlayer(profileID uint32, reason string) {
|
||||
session.Conn.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func KickPlayer(profileID uint32, reason string) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
kickPlayer(profileID, reason)
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ func (g *GameSpySession) login(command common.GameSpyCommand) {
|
||||
g.ModuleName += "/" + common.CalcFriendCodeString(g.User.ProfileId, "RMCJ")
|
||||
|
||||
// Notify QR2 of the login
|
||||
qr2.Login(g.User.ProfileId, gamecd, ingamesn, cfc, g.Conn.RemoteAddr().String(), g.NeedsExploit, g.DeviceAuthenticated, g.User.Restricted)
|
||||
qr2.Login(g.User.ProfileId, gamecd, ingamesn, cfc, g.Conn.RemoteAddr().String(), g.NeedsExploit, g.DeviceAuthenticated, g.User.Restricted, KickPlayer)
|
||||
|
||||
payload := common.CreateGameSpyMessage(common.GameSpyCommand{
|
||||
Command: "lc",
|
||||
|
||||
67
qr2/group.go
67
qr2/group.go
@@ -185,6 +185,73 @@ func ProcessGPStatusUpdate(profileID uint32, senderIP uint64, status string) {
|
||||
}
|
||||
}
|
||||
|
||||
func checkReservationAllowed(moduleName string, sender, destination *Session, joinType byte) string {
|
||||
if sender.Login == nil || destination.Login == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if !sender.Login.Restricted && !destination.Login.Restricted {
|
||||
return "ok"
|
||||
}
|
||||
|
||||
if joinType != 2 && joinType != 3 {
|
||||
return "restricted_join"
|
||||
}
|
||||
|
||||
// TODO: Once OpenHost is implemented, disallow joining public rooms
|
||||
|
||||
if destination.GroupPointer == nil {
|
||||
// Destination is not in a group, check their dwc_mtype instead
|
||||
if destination.Data["dwc_mtype"] != "2" && destination.Data["dwc_mtype"] != "3" {
|
||||
return "restricted_join"
|
||||
}
|
||||
|
||||
// This is fine
|
||||
return "ok"
|
||||
}
|
||||
|
||||
if destination.GroupPointer.MatchType != "private" {
|
||||
return "restricted_join"
|
||||
}
|
||||
|
||||
return "ok"
|
||||
}
|
||||
|
||||
func CheckGPReservationAllowed(senderIP uint64, senderPid uint32, destPid uint32, joinType byte) string {
|
||||
senderPidStr := strconv.FormatUint(uint64(senderPid), 10)
|
||||
destPidStr := strconv.FormatUint(uint64(destPid), 10)
|
||||
|
||||
moduleName := "QR2:CheckReservation:" + senderPidStr + "->" + destPidStr
|
||||
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
from := sessions[senderIP]
|
||||
if from == nil {
|
||||
logging.Error(moduleName, "Sender IP does not exist:", aurora.Cyan(fmt.Sprintf("%012x", senderIP)))
|
||||
return ""
|
||||
}
|
||||
|
||||
toLogin := logins[destPid]
|
||||
if toLogin == nil {
|
||||
logging.Error(moduleName, "Destination profile ID does not exist:", aurora.Cyan(destPid))
|
||||
return ""
|
||||
}
|
||||
|
||||
to := toLogin.Session
|
||||
if to == nil {
|
||||
logging.Error(moduleName, "Destination profile ID does not have a session")
|
||||
return ""
|
||||
}
|
||||
|
||||
// Validate dwc_pid value
|
||||
if !from.setProfileID(moduleName, senderPidStr) || from.Login == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return checkReservationAllowed(moduleName, from, to, joinType)
|
||||
}
|
||||
|
||||
// findNewServer attempts to find the new server/host in the group when the current server goes down.
|
||||
// If no server is found, the group's server pointer is set to nil.
|
||||
// Expects the mutex to be locked.
|
||||
|
||||
@@ -12,8 +12,6 @@ import (
|
||||
|
||||
func heartbeat(moduleName string, conn net.PacketConn, addr net.Addr, buffer []byte) {
|
||||
sessionId := binary.BigEndian.Uint32(buffer[1:5])
|
||||
logging.Info(moduleName, "Received heartbeat; session ID:", aurora.BrightCyan(sessionId))
|
||||
|
||||
values := strings.Split(string(buffer[5:]), "\u0000")
|
||||
|
||||
payload := map[string]string{}
|
||||
@@ -31,6 +29,14 @@ func heartbeat(moduleName string, conn net.PacketConn, addr net.Addr, buffer []b
|
||||
payload[values[i]] = values[i+1]
|
||||
}
|
||||
|
||||
if payload["dwc_mtype"] != "" {
|
||||
logging.Info(moduleName, "Match type:", aurora.Cyan(payload["dwc_mtype"]))
|
||||
}
|
||||
|
||||
if payload["dwc_hoststate"] != "" {
|
||||
logging.Info(moduleName, "Host state:", aurora.Cyan(payload["dwc_hoststate"]))
|
||||
}
|
||||
|
||||
realIP, realPort := common.IPFormatToString(addr.String())
|
||||
|
||||
if ip, ok := payload["publicip"]; !ok || ip == "0" {
|
||||
@@ -94,6 +100,4 @@ func heartbeat(moduleName string, conn net.PacketConn, addr net.Addr, buffer []b
|
||||
}
|
||||
}
|
||||
mutex.Unlock()
|
||||
|
||||
logging.Info(moduleName, "Heartbeat ok")
|
||||
}
|
||||
|
||||
@@ -9,12 +9,13 @@ type LoginInfo struct {
|
||||
NeedsExploit bool
|
||||
DeviceAuthenticated bool
|
||||
Restricted bool
|
||||
GPErrorCallback func(uint32, string)
|
||||
Session *Session
|
||||
}
|
||||
|
||||
var logins = map[uint32]*LoginInfo{}
|
||||
|
||||
func Login(profileID uint32, gameCode string, inGameName string, consoleFriendCode uint64, publicIP string, needsExploit bool, deviceAuthenticated bool, restricted bool) {
|
||||
func Login(profileID uint32, gameCode string, inGameName string, consoleFriendCode uint64, publicIP string, needsExploit bool, deviceAuthenticated bool, restricted bool, gpErrorCallback func(uint32, string)) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
@@ -27,6 +28,7 @@ func Login(profileID uint32, gameCode string, inGameName string, consoleFriendCo
|
||||
NeedsExploit: needsExploit,
|
||||
DeviceAuthenticated: deviceAuthenticated,
|
||||
Restricted: restricted,
|
||||
GPErrorCallback: gpErrorCallback,
|
||||
Session: nil,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,6 +245,31 @@ func SendClientMessage(senderIP string, destSearchID uint64, message []byte) {
|
||||
common.LogMatchCommand(moduleName, destPid, cmd, matchData)
|
||||
|
||||
if cmd == common.MatchReservation {
|
||||
resvError := checkReservationAllowed(moduleName, sender, receiver, matchData.Reservation.MatchType)
|
||||
if resvError != "ok" {
|
||||
if resvError == "restricted" || resvError == "restricted_join" {
|
||||
logging.Error(moduleName, "RESERVATION: Restricted player attempted to join a public match")
|
||||
|
||||
if sender.Login != nil && sender.Login.Restricted {
|
||||
callback := sender.Login.GPErrorCallback
|
||||
profileId := sender.Login.ProfileID
|
||||
|
||||
mutex.Unlock()
|
||||
callback(profileId, resvError)
|
||||
mutex.Lock()
|
||||
}
|
||||
if receiver.Login != nil && receiver.Login.Restricted {
|
||||
callback := receiver.Login.GPErrorCallback
|
||||
profileId := receiver.Login.ProfileID
|
||||
|
||||
mutex.Unlock()
|
||||
callback(profileId, resvError)
|
||||
mutex.Lock()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
sender.Reservation = matchData
|
||||
sender.ReservationID = receiver.SearchID
|
||||
} else if cmd == common.MatchResvOK || cmd == common.MatchResvDeny || cmd == common.MatchResvWait {
|
||||
|
||||
Reference in New Issue
Block a user