Add files via upload

It won't let me add a commit message but I fixed parsing multiple Gamespy messages + the get profile.
This commit is contained in:
Sketch 2023-09-14 00:40:54 -04:00 committed by GitHub
parent 231422c874
commit eb45c1b5cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 141 additions and 65 deletions

View File

@ -16,49 +16,54 @@ var (
InvalidGameSpyCommand = errors.New("invalid command received")
)
func ParseGameSpyMessage(msg string) (*GameSpyCommand, error) {
g := &GameSpyCommand{
OtherValues: map[string]string{},
}
func ParseGameSpyMessage(msg string) ([]GameSpyCommand, error) {
if !strings.Contains(msg, `\\`) || !strings.Contains(msg, `\final\`) {
return nil, InvalidGameSpyCommand
}
foundCommand := false
for len(msg) > 0 {
keyEnd := strings.Index(msg[1:], `\`) + 1
key := msg[1:keyEnd]
value := ""
msg = msg[keyEnd+1:]
if key == "final" {
// We are done.
break
var commands []GameSpyCommand
for len(msg) > 0 && string(msg[0]) == `\` && strings.Contains(msg, `\final\`) {
foundCommand := false
g := GameSpyCommand{
OtherValues: map[string]string{},
}
if strings.Contains(msg, `\`) {
if msg[0] != '\\' {
valueEnd := strings.Index(msg[1:], `\`)
value = msg[:valueEnd+1]
msg = msg[valueEnd+1:]
for len(msg) > 0 && string(msg[0]) == `\` {
keyEnd := strings.Index(msg[1:], `\`) + 1
key := msg[1:keyEnd]
value := ""
msg = msg[keyEnd+1:]
if key == "final" {
// We are done.
break
}
if strings.Contains(msg, `\`) {
if msg[0] != '\\' {
valueEnd := strings.Index(msg[1:], `\`)
value = msg[:valueEnd+1]
msg = msg[valueEnd+1:]
}
} else {
// We have most likely reached the end of the line.
// However, we do not want to exit out without parsing the final key.
value = msg
}
if !foundCommand {
g.Command = key
g.CommandValue = value
foundCommand = true
} else {
g.OtherValues[key] = value
}
} else {
// We have most likely reached the end of the line.
// However, we do not want to exit out without parsing the final key.
value = msg
}
if !foundCommand {
g.Command = key
g.CommandValue = value
foundCommand = true
} else {
g.OtherValues[key] = value
}
commands = append(commands, g)
}
return g, nil
return commands, nil
}
func CreateGameSpyMessage(command GameSpyCommand) string {

View File

@ -16,3 +16,15 @@ func RandomString(n int) string {
}
return string(b)
}
var hexRunes = []rune("0123456789abcdefabcdef")
func RandomHexString(n int) string {
rand.Seed(time.Now().UnixNano())
b := make([]rune, n)
for i := range b {
b[i] = letterRunes[rand.Intn(len(hexRunes))]
}
return string(b)
}

View File

@ -89,7 +89,7 @@ func LoginUserToGCPM(pool *pgxpool.Pool, ctx context.Context, authToken string)
user.CreateUser(pool, ctx)
} else {
// TODO get the profile ID!!!!!
user.ProfileId = 4
user.ProfileId = 474888031
}
return user

View File

@ -10,6 +10,8 @@ import (
const (
InsertUser = `INSERT INTO users (user_id, gsbrcd, password, email, unique_nick) VALUES ($1, $2, $3, $4, $5) RETURNING profile_id`
UpdateUserTable = `UPDATE users SET firstname = $1, lastname = $2 WHERE user_id = $3`
GetUser = `SELECT user_id, gsbrcd, password, email, unique_nick, firstname, lastname FROM users WHERE profile_id = $1`
CreateUserSession = `INSERT INTO sessions (session_key, profile_id, login_ticket) VALUES ($1, $2, $3)`
DoesUserExist = `SELECT EXISTS(SELECT 1 FROM users WHERE user_id = $1 AND gsbrcd = $2)`
DeleteUserSession = `DELETE FROM sessions WHERE profile_id = $1`
@ -22,6 +24,8 @@ type User struct {
Password string
Email string
UniqueNick string
FirstName string
LastName string
}
func (user *User) CreateUser(pool *pgxpool.Pool, ctx context.Context) {
@ -31,6 +35,16 @@ func (user *User) CreateUser(pool *pgxpool.Pool, ctx context.Context) {
}
}
func UpdateUser(pool *pgxpool.Pool, ctx context.Context, firstName string, lastName string, userId int) User {
user := User{}
_, err := pool.Exec(ctx, UpdateUserTable, firstName, lastName, userId)
if err != nil {
panic(err)
}
return user
}
func CreateSession(pool *pgxpool.Pool, ctx context.Context, profileId int, loginTicket string) string {
// Delete session first.
deleteSession(pool, ctx, profileId)
@ -51,6 +65,13 @@ func deleteSession(pool *pgxpool.Pool, ctx context.Context, profileId int) {
}
}
func GetProfile(pool *pgxpool.Pool, ctx context.Context) {
func GetProfile(pool *pgxpool.Pool, ctx context.Context, profileId int) User {
user := User{}
row := pool.QueryRow(ctx, GetUser, profileId)
err := row.Scan(&user.UserId, &user.GsbrCode, &user.Password, &user.Email, &user.UniqueNick, &user.FirstName, &user.LastName)
if err != nil {
panic(err)
}
return user
}

View File

@ -32,7 +32,7 @@ func generateProof(gpcmChallenge, nasChallenge, authToken, clientChallenge strin
return generateResponse(clientChallenge, nasChallenge, authToken, gpcmChallenge)
}
func login(pool *pgxpool.Pool, ctx context.Context, command *common.GameSpyCommand, challenge string) string {
func login(pool *pgxpool.Pool, ctx context.Context, command common.GameSpyCommand, challenge string) string {
// TODO: Validate login token with one in database
authToken := command.OtherValues["authtoken"]
response := generateResponse(challenge, "0qUekMb4", authToken, command.OtherValues["challenge"])
@ -45,7 +45,8 @@ func login(pool *pgxpool.Pool, ctx context.Context, command *common.GameSpyComma
// Perform the login with the database.
user := database.LoginUserToGCPM(pool, ctx, authToken)
loginTicket := strings.Replace(base64.StdEncoding.EncodeToString([]byte(common.RandomString(16))), "=", "_", -1)
// TODO: REMOVE!!!!!
userId = user.UserId
// Now initiate the session
_ = database.CreateSession(pool, ctx, user.ProfileId, loginTicket)

View File

@ -16,8 +16,9 @@ import (
)
var (
ctx = context.Background()
pool *pgxpool.Pool
ctx = context.Background()
pool *pgxpool.Pool
userId int
)
func checkError(err error) {
@ -89,25 +90,31 @@ func handleRequest(conn net.Conn) {
}
}
command, err := common.ParseGameSpyMessage(string(buffer))
commands, err := common.ParseGameSpyMessage(string(buffer))
if err != nil {
log.Fatal(err)
}
log.Printf("%s: Message received. Command: %s", aurora.Green("[NOTICE]"), aurora.Yellow(command.Command))
switch command.Command {
case "ka":
conn.Write([]byte(`\ka\final\`))
break
case "login":
payload := login(pool, ctx, command, challenge)
conn.Write([]byte(payload))
break
case "getprofile":
payload := getProfile(pool, ctx, command)
fmt.Println(payload)
conn.Write([]byte(payload))
break
for _, command := range commands {
log.Printf("%s: Message received. Command: %s", aurora.Green("[NOTICE]"), aurora.Yellow(command.Command))
switch command.Command {
case "ka":
conn.Write([]byte(`\ka\\final\`))
break
case "login":
payload := login(pool, ctx, command, challenge)
conn.Write([]byte(payload))
break
case "getprofile":
payload := getProfile(pool, ctx, command)
fmt.Println(payload)
conn.Write([]byte(payload))
break
case "updatepro":
// Nothing is written here.
updateProfile(pool, ctx, command)
break
}
}
}
}

View File

@ -2,28 +2,31 @@ package gpcm
import (
"context"
"encoding/hex"
"fmt"
"github.com/jackc/pgx/v4/pgxpool"
"strconv"
"wwfc/common"
"wwfc/database"
)
func getProfile(pool *pgxpool.Pool, ctx context.Context, command *common.GameSpyCommand) string {
for k, v := range command.OtherValues {
fmt.Println(fmt.Sprintf("%s: %s", k, v))
}
func getProfile(pool *pgxpool.Pool, ctx context.Context, command common.GameSpyCommand) string {
strProfileId := command.OtherValues["profileid"]
profileId, _ := strconv.Atoi(strProfileId)
sig := hex.EncodeToString([]byte(common.RandomString(16)))
user := database.GetProfile(pool, ctx, profileId)
_ = common.RandomHexString(32)
return common.CreateGameSpyMessage(common.GameSpyCommand{
Command: "pi",
CommandValue: "",
OtherValues: map[string]string{
"profileid": command.OtherValues["profileid"],
"nick": "7me4ijr5sRMCJ23ul711",
"userid": "8467681766588",
"email": "7me4ijr5sRMCJ23ul711@nds",
"sig": sig,
"uniquenick": "7me4ijr5sRMCJ23ul711",
"nick": user.UniqueNick,
"userid": strconv.Itoa(user.UserId),
"email": user.Email,
"sig": "b126556e5ee62d4da9629dfad0f6b2a8",
"uniquenick": user.UniqueNick,
"firstname": user.FirstName,
"lastname": user.LastName,
"pid": "11",
"lon": "0.000000",
"lat": "0.000000",
@ -32,3 +35,28 @@ func getProfile(pool *pgxpool.Pool, ctx context.Context, command *common.GameSpy
},
})
}
func updateProfile(pool *pgxpool.Pool, ctx context.Context, command common.GameSpyCommand) {
var firstName string
var lastName string
if v, ok := command.OtherValues["firstname"]; ok {
firstName = v
}
if v, ok := command.OtherValues["lastname"]; ok {
lastName = v
}
database.UpdateUser(pool, ctx, firstName, lastName, userId)
}
func createStatus() string {
return common.CreateGameSpyMessage(common.GameSpyCommand{
Command: "bm",
CommandValue: "100",
OtherValues: map[string]string{
"f": "5",
"msg": "|s|0|ss|Offline",
},
})
}

View File

@ -2,6 +2,7 @@ package nas
import (
"encoding/base64"
"fmt"
"github.com/logrusorgru/aurora/v3"
"log"
"net/http"
@ -59,6 +60,7 @@ func (route *Route) Handle() http.Handler {
path := strings.Replace(r.URL.Path, "/", "", -1)
actionName, _ := base64.StdEncoding.DecodeString(strings.Replace(r.PostForm.Get("action"), "*", "=", -1))
fmt.Println(string(actionName))
var action Action
for _, _action := range route.Actions {
if path == _action.ServiceType && string(actionName) == _action.ActionName {