dkforest

A forum and chat platform (onion)
git clone https://git.dasho.dev/n0tr1v/dkforest.git
Log | Files | Refs | LICENSE

commit 0f588d2c7a716749923b190ede33519b5de06271
parent 3caebb0e954b778432e5655b7541c68265e151c5
Author: n0tr1v <n0tr1v@protonmail.com>
Date:   Fri, 12 Jan 2024 13:21:44 -0800

verify auth for quoted messages

Diffstat:
Mpkg/database/utils/processMessage.go | 14++++++++------
Mpkg/database/utils/utils.go | 22++++++++++++++++++++++
Mpkg/web/handlers/api/v1/chat.go | 24+-----------------------
Mpkg/web/handlers/chat.go | 3+--
Mpkg/web/handlers/interceptors/bangInterceptor.go | 2+-
Mpkg/web/handlers/interceptors/command/command.go | 2+-
Mpkg/web/handlers/interceptors/msgInterceptor.go | 2+-
Mpkg/web/handlers/interceptors/slashInterceptor.go | 2+-
Mpkg/web/handlers/interceptors/werewolf.go | 2+-
9 files changed, 37 insertions(+), 36 deletions(-)

diff --git a/pkg/database/utils/processMessage.go b/pkg/database/utils/processMessage.go @@ -105,8 +105,8 @@ var msgPolicy = bluemonday.NewPolicy(). // ProcessRawMessage return the new html, and a map of tagged users used for notifications // This function takes an "unsafe" user input "in", and return html which will be safe to render. func ProcessRawMessage(db *database.DkfDB, in, roomKey string, authUserID database.UserID, roomID database.RoomID, - upload *database.Upload, canUseMultiline, manualML bool) (string, map[database.UserID]database.User, error) { - html, quoted := convertQuote(db, in, roomKey, roomID) // Get raw quote text which is not safe to render + upload *database.Upload, isModerator, canUseMultiline, manualML bool) (string, map[database.UserID]database.User, error) { + html, quoted := convertQuote(db, in, roomKey, roomID, authUserID, isModerator) // Get raw quote text which is not safe to render html = convertNewLines(html, canUseMultiline) html = html2.EscapeString(html) // Makes user input safe to render // All html generated from this point on shall be safe to render. @@ -140,7 +140,7 @@ func ProcessRawMessage(db *database.DkfDB, in, roomKey string, authUserID databa // eg: we received altered quote, and return original quote -> // “[01:23:45] username - Some maliciously altered quote” Some text // “[01:23:45] username - The original text” Some text -func convertQuote(db *database.DkfDB, origHtml string, roomKey string, roomID database.RoomID) (html string, quoted *database.ChatMessage) { +func convertQuote(db *database.DkfDB, origHtml, roomKey string, roomID database.RoomID, authUserID database.UserID, isModerator bool) (html string, quoted *database.ChatMessage) { const quotePrefix = `“[` const quoteSuffix = `”` html = origHtml @@ -156,7 +156,7 @@ func convertQuote(db *database.DkfDB, origHtml string, roomKey string, roomID da if spaceIdx >= 3 { username = database.Username(origHtml[usernameStartIdx : spaceIdx+usernameStartIdx]) } - if quoted = getQuotedChatMessage(db, hourMinSec, username, roomID); quoted != nil { + if quoted = getQuotedChatMessage(db, hourMinSec, username, roomID, authUserID, isModerator); quoted != nil { html = GetQuoteTxt(db, roomKey, *quoted) html += origHtml[idx+suffixLen:] } @@ -166,7 +166,7 @@ func convertQuote(db *database.DkfDB, origHtml string, roomKey string, roomID da } // Given a roomID and hourMinSec (01:23:45) and a username, retrieve the message from database that fits the predicates. -func getQuotedChatMessage(db *database.DkfDB, hourMinSec string, username database.Username, roomID database.RoomID) (quoted *database.ChatMessage) { +func getQuotedChatMessage(db *database.DkfDB, hourMinSec string, username database.Username, roomID database.RoomID, authUserID database.UserID, isModerator bool) (quoted *database.ChatMessage) { if dt, err := utils.ParsePrevDatetimeAt(hourMinSec, clockwork.NewRealClock()); err == nil { if msgs, err := db.GetRoomChatMessagesByDate(roomID, dt.UTC()); err == nil && len(msgs) > 0 { msg := msgs[0] @@ -178,7 +178,9 @@ func getQuotedChatMessage(db *database.DkfDB, hourMinSec string, username databa } } } - quoted = &msg + if VerifyMsgAuth(db, &msg, authUserID, isModerator) { + quoted = &msg + } } } return diff --git a/pkg/database/utils/utils.go b/pkg/database/utils/utils.go @@ -255,3 +255,25 @@ func CanUserPmOther(db *database.DkfDB, user, other database.User, roomIsPrivate // Should never go here return false, nil } + +// VerifyMsgAuth returns either or not authUser is allowed to see msg +func VerifyMsgAuth(db *database.DkfDB, msg *database.ChatMessage, authUserID database.UserID, isModerator bool) bool { + // Verify moderators channel authorization + if msg.Moderators && !isModerator { + return false + } + // Verify group authorization + if msg.GroupID != nil { + userGroupsIDs, _ := db.GetUserRoomGroupsIDs(authUserID, msg.RoomID) + if !utils.InArr(*msg.GroupID, userGroupsIDs) { + return false + } + } + // verify PM authorization + if msg.IsPm() { + if msg.UserID != authUserID && *msg.ToUserID != authUserID { + return false + } + } + return true +} diff --git a/pkg/web/handlers/api/v1/chat.go b/pkg/web/handlers/api/v1/chat.go @@ -21,28 +21,6 @@ import ( "time" ) -// VerifyMsgAuth returns either or not authUser is allowed to see msg -func VerifyMsgAuth(db *database.DkfDB, authUser database.IUserRenderMessage, msg *database.ChatMessage) bool { - // Verify moderators channel authorization - if msg.Moderators && !authUser.IsModerator() { - return false - } - // Verify group authorization - if msg.GroupID != nil { - userGroupsIDs, _ := db.GetUserRoomGroupsIDs(authUser.GetID(), msg.RoomID) - if !utils.InArr(*msg.GroupID, userGroupsIDs) { - return false - } - } - // verify PM authorization - if msg.IsPm() { - if msg.UserID != authUser.GetID() && *msg.ToUserID != authUser.GetID() { - return false - } - } - return true -} - func manualPreload(db *database.DkfDB, msg *database.ChatMessage, room database.ChatRoom) { if msg.GroupID != nil { if msg.Group == nil { @@ -394,7 +372,7 @@ Loop: } } - if !VerifyMsgAuth(db, authUser1, msg) || + if !dutils.VerifyMsgAuth(db, msg, authUser1.GetID(), authUser1.IsModerator()) || !applyUserFilters(db, authUser1, msg, pmUserID, pmOnlyQuery, displayHellbanned, mentionsOnlyQuery) { continue } diff --git a/pkg/web/handlers/chat.go b/pkg/web/handlers/chat.go @@ -8,7 +8,6 @@ import ( "dkforest/pkg/hashset" "dkforest/pkg/managers" "dkforest/pkg/utils" - v1 "dkforest/pkg/web/handlers/api/v1" hutils "dkforest/pkg/web/handlers/utils" "github.com/PuerkitoBio/goquery" "github.com/asaskevich/govalidator" @@ -399,7 +398,7 @@ func ChatCodeHandler(c echo.Context) error { return c.Redirect(http.StatusFound, "/") } - if !v1.VerifyMsgAuth(db, authUser, &msg) { + if !dutils.VerifyMsgAuth(db, &msg, authUser.ID, authUser.IsModerator()) { return c.Redirect(http.StatusFound, "/") } diff --git a/pkg/web/handlers/interceptors/bangInterceptor.go b/pkg/web/handlers/interceptors/bangInterceptor.go @@ -24,7 +24,7 @@ Chats: Black Hat Chat: ` + config.BhcOnion + ` Forums: CryptBB: ` + config.CryptbbOnion - msg, _, _ := dutils.ProcessRawMessage(cmd.DB, message, "", cmd.AuthUser.ID, cmd.Room.ID, nil, true, false) + msg, _, _ := dutils.ProcessRawMessage(cmd.DB, message, "", cmd.AuthUser.ID, cmd.Room.ID, nil, cmd.AuthUser.IsModerator(), true, false) cmd.ZeroMsg(msg) cmd.Err = command.ErrRedirect } diff --git a/pkg/web/handlers/interceptors/command/command.go b/pkg/web/handlers/interceptors/command/command.go @@ -124,7 +124,7 @@ func (c *Command) zeroProcMsgRoom(rawMsg, roomKey string, roomID database.RoomID // Have the "zero user" send a "processed message" PM to a user in a specific room. func (c *Command) zeroProcMsgRoomToUser(rawMsg, roomKey string, roomID database.RoomID, toUser *database.User) { - procMsg, _, _ := dutils.ProcessRawMessage(c.DB, rawMsg, roomKey, c.AuthUser.ID, roomID, nil, true, false) + procMsg, _, _ := dutils.ProcessRawMessage(c.DB, rawMsg, roomKey, c.AuthUser.ID, roomID, nil, c.AuthUser.IsModerator(), true, false) c.zeroRawMsg(toUser, rawMsg, procMsg) } diff --git a/pkg/web/handlers/interceptors/msgInterceptor.go b/pkg/web/handlers/interceptors/msgInterceptor.go @@ -103,7 +103,7 @@ func (i MsgInterceptor) InterceptMsg(cmd *command.Command) { return } - html, taggedUsersIDsMap, err := dutils.ProcessRawMessage(cmd.DB, cmd.Message, cmd.RoomKey, cmd.AuthUser.ID, cmd.Room.ID, cmd.Upload, cmd.AuthUser.CanUseMultiline, cmd.AuthUser.ManualMultiline) + html, taggedUsersIDsMap, err := dutils.ProcessRawMessage(cmd.DB, cmd.Message, cmd.RoomKey, cmd.AuthUser.ID, cmd.Room.ID, cmd.Upload, cmd.AuthUser.IsModerator(), cmd.AuthUser.CanUseMultiline, cmd.AuthUser.ManualMultiline) if err != nil { cmd.DataMessage = cmd.OrigMessage cmd.Err = err diff --git a/pkg/web/handlers/interceptors/slashInterceptor.go b/pkg/web/handlers/interceptors/slashInterceptor.go @@ -1300,7 +1300,7 @@ func handleInboxCmd(c *command.Command) (handled bool) { inboxHTML = strings.Join(strings.Split(inboxHTML, "\n"), " ") } - inboxHTML, _, _ = dutils.ProcessRawMessage(c.DB, inboxHTML, c.RoomKey, c.AuthUser.ID, c.Room.ID, nil, c.AuthUser.CanUseMultiline, c.AuthUser.ManualMultiline) + inboxHTML, _, _ = dutils.ProcessRawMessage(c.DB, inboxHTML, c.RoomKey, c.AuthUser.ID, c.Room.ID, nil, c.AuthUser.IsModerator(), c.AuthUser.CanUseMultiline, c.AuthUser.ManualMultiline) c.DB.CreateInboxMessage(inboxHTML, c.Room.ID, c.AuthUser.ID, toUser.ID, true, false, nil) c.DataMessage = "/inbox " + string(username) + " " diff --git a/pkg/web/handlers/interceptors/werewolf.go b/pkg/web/handlers/interceptors/werewolf.go @@ -331,7 +331,7 @@ func (b *Werewolf) isValidPlayerName(name string) bool { // Narrate register a chat message on behalf of the narrator user func (b *Werewolf) Narrate(msg string, toUserID *database.UserID, groupID *database.GroupID) { - html, _, _ := dutils.ProcessRawMessage(b.db, msg, "", b.narratorID, b.roomID, nil, true, false) + html, _, _ := dutils.ProcessRawMessage(b.db, msg, "", b.narratorID, b.roomID, nil, false, true, false) b.NarrateRaw(html, toUserID, groupID) }