From eb45c1b5cc7be80e41d3dc9d6ca389edf7cdd2fe Mon Sep 17 00:00:00 2001 From: Sketch <75850871+noahpistilli@users.noreply.github.com> Date: Thu, 14 Sep 2023 00:40:54 -0400 Subject: [PATCH] Add files via upload It won't let me add a commit message but I fixed parsing multiple Gamespy messages + the get profile. --- common/gamespy_message.go | 69 +++++++++++++++++++++------------------ common/utils.go | 12 +++++++ database/login.go | 2 +- database/user.go | 23 ++++++++++++- gpcm/login.go | 5 +-- gpcm/main.go | 41 +++++++++++++---------- gpcm/profile.go | 52 ++++++++++++++++++++++------- nas/route.go | 2 ++ 8 files changed, 141 insertions(+), 65 deletions(-) diff --git a/common/gamespy_message.go b/common/gamespy_message.go index cf5e653..a5fe25a 100644 --- a/common/gamespy_message.go +++ b/common/gamespy_message.go @@ -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 { diff --git a/common/utils.go b/common/utils.go index fa74047..dd284b2 100644 --- a/common/utils.go +++ b/common/utils.go @@ -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) +} diff --git a/database/login.go b/database/login.go index 974a9c7..39123c8 100644 --- a/database/login.go +++ b/database/login.go @@ -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 diff --git a/database/user.go b/database/user.go index 4f25c54..1c22ea2 100644 --- a/database/user.go +++ b/database/user.go @@ -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 } diff --git a/gpcm/login.go b/gpcm/login.go index f32a53a..f2669cb 100644 --- a/gpcm/login.go +++ b/gpcm/login.go @@ -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) diff --git a/gpcm/main.go b/gpcm/main.go index 86820ca..8fe0ace 100644 --- a/gpcm/main.go +++ b/gpcm/main.go @@ -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 + } } } } diff --git a/gpcm/profile.go b/gpcm/profile.go index a1c6d78..eaa1256 100644 --- a/gpcm/profile.go +++ b/gpcm/profile.go @@ -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", + }, + }) +} diff --git a/nas/route.go b/nas/route.go index 74da67f..5072187 100644 --- a/nas/route.go +++ b/nas/route.go @@ -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 {