func RPCAuthenticateWithKeyMessage(conn net.Conn, connection_data *structs.ConnData, packet_data *structs.PacketData) error { // Unmarshal the data msg := new(protocol.AuthenticateWithKeyMessage) err := proto.Unmarshal(packet_data.Content, msg) if err != nil { return err } // Generate a new connection-id based npid npid := structs.IdToNpid(connection_data.ConnectionId) // Fill in the connection data connection_data.Authenticated = true connection_data.IsServer = true connection_data.Token = "" connection_data.Npid = npid // Add connection to the storage storage.SetServerConnection(npid, connection_data) // Reply with the data return reply.Reply(conn, packet_data.Header.Id, &protocol.AuthenticateResultMessage{ Result: proto.Int32(0), Npid: proto.Uint64(npid), SessionToken: []byte(""), }) }
func KickUser(serverID uint64, clientID uint64, reason int64) error { data := storage.GetServerConnection(serverID) if data != nil { return reply.Reply(data.Connection, 0, &protocol.AuthenticateKickUserMessage{ Npid: proto.Uint64(clientID), Reason: proto.Int32(1), ReasonString: proto.String("Cheat detected (" + strconv.FormatInt(reason, 10) + ")"), }) } return ServerDisappeared }
func RPCFriendsGetUserAvatarMessage(conn net.Conn, connection_data *structs.ConnData, packet_data *structs.PacketData) error { // Unmarshal the message msg := new(protocol.FriendsGetUserAvatarMessage) err := proto.Unmarshal(packet_data.Content, msg) if err != nil { return err } mutexCreation.Lock() mutex, exists := downloadMutexes[msg.GetGuid()] if !exists { downloadMutexes[msg.GetGuid()] = new(sync.Mutex) mutex = downloadMutexes[msg.GetGuid()] } mutexCreation.Unlock() mutex.Lock() defer mutex.Unlock() // Check for data in the cache cached, ok := avatarCache[msg.GetGuid()] if ok { //logger.Errorf("Getting %d avatar from cache", msg.GetGuid()) return reply.Reply(conn, packet_data.Header.Id, &protocol.FriendsGetUserAvatarResultMessage{ Result: proto.Int32(0), Guid: msg.Guid, FileData: cached, }) } // Query the database for the avatar info var rows []*struct { Email string Type string Image string } err = environment.Env.Database.Query(` SELECT email, avatar_type as type, avatar_image as image FROM misago_user WHERE id = ?`, int(msg.GetGuid())).Rows(&rows) // Query error, something's wrong! if err != nil { return err } // No user found, might be a bug or invalid client request if len(rows) < 1 { return nil } // Load file from disk if rows[0].Type == "upload" { // Generate the filepath filename := filepath.Join(environment.Env.Config.NP.AvatarsPath, rows[0].Image) //logger.Errorf("Getting %d avatar from disk; %s", msg.GetGuid(), filename) // Ensure the file exists if !utility.FileExists(filename) { return nil } // Read file contents filecontents, err := ioutil.ReadFile(filename) if err != nil { return err } // Get the extension of the file ext := filepath.Ext(filename) // Convert from jpg to png if ext == ".jpg" || ext == ".jpeg" { rd := bytes.NewReader(filecontents) img, err := jpeg.Decode(rd) if err != nil { return err } buf := make([]byte, 0) wr := bytes.NewBuffer(buf) err = png.Encode(wr, img) if err != nil { return err } filecontents = wr.Bytes() } // Convert from gif to png if ext == ".gif" { rd := bytes.NewReader(filecontents) img, err := gif.Decode(rd) if err != nil { return err } buf := make([]byte, 0) wr := bytes.NewBuffer(buf) err = png.Encode(wr, img) if err != nil { return err } filecontents = wr.Bytes() } // Cache it avatarCache[msg.GetGuid()] = filecontents //avatarCache.Set(strconv.Itoa(int(msg.GetGuid())), filecontents, -1) // Return it to the client return reply.Reply(conn, packet_data.Header.Id, &protocol.FriendsGetUserAvatarResultMessage{ Result: proto.Int32(0), Guid: msg.Guid, FileData: filecontents, }) } else if rows[0].Type == "gravatar" { // Download the avatar data, err := gravatar.GetAvatar("http", gravatar.EmailHash(rows[0].Email), 96, gravatar.DefaultIdentIcon) if err != nil { return err } //logger.Errorf("Getting %d avatar from internet; %s", msg.GetGuid(), rows[0].Email) // Cache it //avatarCache.Set(strconv.Itoa(int(msg.GetGuid())), data, -1) avatarCache[msg.GetGuid()] = data // Return it to the client return reply.Reply(conn, packet_data.Header.Id, &protocol.FriendsGetUserAvatarResultMessage{ Result: proto.Int32(0), Guid: msg.Guid, FileData: data, }) } return nil }
func RPCAuthenticateValidateTicketMessage(conn net.Conn, connection_data *structs.ConnData, packet_data *structs.PacketData) error { // Unmarshal the data msg := new(protocol.AuthenticateValidateTicketMessage) err := proto.Unmarshal(packet_data.Content, msg) if err != nil { return err } // Create a new buffer based on the ticket data, in order to read data from it. buf := bytes.NewBuffer(msg.Ticket) // Structure: // <xxxx> <xxxxxxxx> <xxxxxxxx> <xxxx> // version clientID serverID timeIssued var version, issued uint32 var clientId, serverId uint64 err = binary.Read(buf, binary.LittleEndian, &version) if err != nil { return err } err = binary.Read(buf, binary.LittleEndian, &clientId) if err != nil { return err } err = binary.Read(buf, binary.LittleEndian, &serverId) if err != nil { return err } err = binary.Read(buf, binary.LittleEndian, &issued) if err != nil { return err } // Only version 1 is valid if version == 1 { // Verify that the request isn't spoofed if connection_data.Npid == serverId { // Get client's connection session := storage.GetClientConnection(clientId) // Make sure the session is here if session == nil { return nil } // Make sure it's not a server if session.IsServer { return nil } // Make sure that the IDs are valid if session.Npid != clientId { return reply.Reply(conn, packet_data.Header.Id, &protocol.AuthenticateValidateTicketResultMessage{ Result: proto.Int32(1), Npid: &clientId, GroupID: proto.Int32(1), }) } // Make sure there's no aCI detection if session.IsUnclean { return reply.Reply(conn, packet_data.Header.Id, &protocol.AuthenticateValidateTicketResultMessage{ Result: proto.Int32(1), Npid: &clientId, GroupID: proto.Int32(1), }) } // Set the server ID session.ServerId = serverId // Heartbeat detection /*time.AfterFunc(time.Minute*2, func() { if session != nil && session.Valid && session.Username != "" && !session.IsUnclean { if session.LastCI.IsZero() { //Before(time.Now().Truncate(time.Minute)) { err = utils.BanUser(session.Username, 10000, time.Hour*24*14) if err != nil { logger.Warning(err) } err = utils.KickUser(serverId, session.Npid, 10000) if err != nil { logger.Warning(err) } session.IsUnclean = true } } })*/ // Reply that everything is fine return reply.Reply(conn, packet_data.Header.Id, &protocol.AuthenticateValidateTicketResultMessage{ Result: proto.Int32(0), Npid: &clientId, GroupID: proto.Int32(1), }) } } // Wrong version or wrong NPID return reply.Reply(conn, packet_data.Header.Id, &protocol.AuthenticateValidateTicketResultMessage{ Result: proto.Int32(1), Npid: &clientId, GroupID: proto.Int32(1), }) }
func RPCAuthenticateWithTokenMessage(conn net.Conn, connection_data *structs.ConnData, packet_data *structs.PacketData) error { // Unmarshal the data msg := new(protocol.AuthenticateWithTokenMessage) err := proto.Unmarshal(packet_data.Content, msg) if err != nil { return err } // Split the token token := string(msg.Token) parts := strings.Split(token, ":") // uid is the first part id, err := strconv.Atoi(parts[0]) if err != nil { return err } // Convert it to the Npid npid := structs.IdToNpid(id) // Set connection data connection_data.Id = id connection_data.Npid = npid connection_data.Token = token // Verify! sess_string, err := environment.Env.Redis.Get("session:" + token).Result() if err != nil { return err } // Format is: ip;rank;username sess_parts := strings.Split(sess_string, ";") // Verify that user has the same IP as the one used to log in if sess_parts[0] != structs.StripPort(conn.RemoteAddr().String()) { return WrongIPAddress } // Get the rank id and save it in the session connection_data.RankId, err = strconv.Atoi(sess_parts[1]) if err != nil { return err } // Authenticate the session connection_data.Authenticated = true connection_data.Username = sess_parts[2] // Add connection to the storage storage.SetClientConnection(npid, connection_data) // Return a response err = reply.Reply(conn, packet_data.Header.Id, &protocol.AuthenticateResultMessage{ Result: proto.Int32(0), Npid: &npid, SessionToken: msg.Token, }) if err != nil { return err } // No idea what this thing is supposed to do time.AfterFunc(time.Millisecond*900, func() { err = reply.Reply(conn, 0, &protocol.AuthenticateExternalStatusMessage{ Status: proto.Int32(0), }) if err != nil { logger.Warning(err) } }) return nil }