From 4972cb6d5e68c0ad9f7b290e33f49ecf6436361b Mon Sep 17 00:00:00 2001 From: Bohdan Horbeshko Date: Wed, 4 Oct 2023 05:57:29 -0400 Subject: [PATCH] Reject MUC nickname change attempts --- telegram/utils.go | 33 +++++++++++++++++++++ xmpp/handlers.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/telegram/utils.go b/telegram/utils.go index addeee8..a730113 100644 --- a/telegram/utils.go +++ b/telegram/utils.go @@ -478,6 +478,39 @@ func (c *Client) updateMUCsNickname(memberID int64, newNickname string) { } } +// MUCHasResource checks if a MUC was joined from a given resource +func (c *Client) MUCHasResource(chatID int64, resource string) bool { + c.locks.mucCacheLock.Lock() + defer c.locks.mucCacheLock.Unlock() + + mucState, ok := c.mucCache[chatID] + if !ok || mucState == nil { + return false + } + _, ok = mucState.Resources[resource] + return ok +} + +// GetMyMUCNickname obtains this account's nickname in a given MUC +func (c *Client) GetMyMUCNickname(chatID int64) (string, bool) { + if c.me == nil { + return "", false + } + + c.locks.mucCacheLock.Lock() + defer c.locks.mucCacheLock.Unlock() + + mucState, ok := c.mucCache[chatID] + if !ok || mucState == nil { + return "", false + } + member, ok := mucState.Members[c.me.Id] + if !ok { + return "", false + } + return member.Nickname, true +} + func (c *Client) formatContact(chatID int64) string { if chatID == 0 { return "" diff --git a/xmpp/handlers.go b/xmpp/handlers.go index 3ab79c7..eea14be 100644 --- a/xmpp/handlers.go +++ b/xmpp/handlers.go @@ -324,7 +324,9 @@ func HandlePresence(s xmpp.Sender, p stanza.Packet) { prs.Get(&mucExt) if mucExt.XMLName.Space != "" { handleMUCPresence(s, prs, mucExt) + return } + tryHandleMUCNicknameChange(s, prs) } func handleSubscription(s xmpp.Sender, p stanza.Presence) { @@ -498,6 +500,77 @@ func handleMUCPresence(s xmpp.Sender, p stanza.Presence, mucExt stanza.MucPresen } } +func tryHandleMUCNicknameChange(s xmpp.Sender, p stanza.Presence) { + log.WithFields(log.Fields{ + "type": p.Type, + "from": p.From, + "to": p.To, + }).Warn("Nickname change presence?") + log.Debugf("%#v", p) + + if p.Type != "" { + return + } + + toBare, nickname, ok := gateway.SplitJID(p.To) + if !ok || nickname == "" { + return + } + + fromBare, fromResource, ok := gateway.SplitJID(p.From) + if !ok { + return + } + + session, ok := sessions[fromBare] + if !ok || !session.Session.MUC { + return + } + + chatId, ok := toToID(toBare) + if !ok { + return + } + + chat, _, err := session.GetContactByID(chatId, nil) + if err != nil || !session.IsGroup(chat) { + return + } + + if !session.MUCHasResource(chatId, fromResource) { + return + } + + log.Warn("🗿 Yes") + + component, ok := s.(*xmpp.Component) + if !ok { + log.Error("Not a component") + return + } + + from := toBare + nickname, ok = session.GetMyMUCNickname(chatId) + if ok { + from = from+"/"+nickname + } + reply := &stanza.Presence{ + Attrs: stanza.Attrs{ + From: from, + To: p.From, + Id: p.Id, + Type: stanza.PresenceTypeError, + }, + Error: stanza.Err{ + Code: 406, + Type: stanza.ErrorTypeModify, + Reason: "not-acceptable", + Text: "Telegram does not support changing nicknames per-chat. Issue a /setname command to the transport if you wish to change the global name", + }, + } + gateway.ResumableSend(component, reply) +} + func handleGetVcardIq(s xmpp.Sender, iq *stanza.IQ, typ byte) { log.WithFields(log.Fields{ "from": iq.From,