fix access checks; fix duplicate metadata message; better email sanitization

This commit is contained in:
Aine
2024-02-05 21:49:30 +02:00
parent 32b80191a3
commit 0bd2fc525e
4 changed files with 38 additions and 27 deletions

View File

@@ -22,14 +22,24 @@ func parseMXIDpatterns(patterns []string, defaultPattern string) ([]*regexp.Rege
return mxidwc.ParsePatterns(patterns) return mxidwc.ParsePatterns(patterns)
} }
func (b *Bot) allowUsers(actorID id.UserID) bool { func (b *Bot) allowUsers(actorID id.UserID, targetRoomID id.RoomID) bool {
if len(b.allowedUsers) != 0 { // first, check if it's an allowed user
if !mxidwc.Match(actorID.String(), b.allowedUsers) { if mxidwc.Match(actorID.String(), b.allowedUsers) {
return false return true
}
} }
// second, check if it's an admin (admin may not fit the allowed users pattern)
if b.allowAdmin(actorID, targetRoomID) {
return true return true
}
// then, check if it's the owner (same as above)
cfg, err := b.cfg.GetRoom(targetRoomID)
if err == nil && cfg.Owner() == actorID.String() {
return true
}
return false
} }
func (b *Bot) allowAnyone(_ id.UserID, _ id.RoomID) bool { func (b *Bot) allowAnyone(_ id.UserID, _ id.RoomID) bool {
@@ -37,7 +47,7 @@ func (b *Bot) allowAnyone(_ id.UserID, _ id.RoomID) bool {
} }
func (b *Bot) allowOwner(actorID id.UserID, targetRoomID id.RoomID) bool { func (b *Bot) allowOwner(actorID id.UserID, targetRoomID id.RoomID) bool {
if !b.allowUsers(actorID) { if !b.allowUsers(actorID, targetRoomID) {
return false return false
} }
cfg, err := b.cfg.GetRoom(targetRoomID) cfg, err := b.cfg.GetRoom(targetRoomID)
@@ -59,7 +69,7 @@ func (b *Bot) allowAdmin(actorID id.UserID, _ id.RoomID) bool {
} }
func (b *Bot) allowSend(actorID id.UserID, targetRoomID id.RoomID) bool { func (b *Bot) allowSend(actorID id.UserID, targetRoomID id.RoomID) bool {
if !b.allowUsers(actorID) { if !b.allowUsers(actorID, targetRoomID) {
return false return false
} }
@@ -73,7 +83,7 @@ func (b *Bot) allowSend(actorID id.UserID, targetRoomID id.RoomID) bool {
} }
func (b *Bot) allowReply(actorID id.UserID, targetRoomID id.RoomID) bool { func (b *Bot) allowReply(actorID id.UserID, targetRoomID id.RoomID) bool {
if !b.allowUsers(actorID) { if !b.allowUsers(actorID, targetRoomID) {
return false return false
} }

View File

@@ -3,7 +3,9 @@ package bot
import ( import (
"context" "context"
"errors" "errors"
"fmt"
"strings" "strings"
"time"
"gitlab.com/etke.cc/linkpearl" "gitlab.com/etke.cc/linkpearl"
"maunium.net/go/mautrix/event" "maunium.net/go/mautrix/event"
@@ -71,7 +73,7 @@ func (b *Bot) Sendmail(eventID id.EventID, from, to, data string) (bool, error)
return false, err return false, err
} }
log.Warn().Err(err).Msg("email delivery succeeded") log.Info().Msg("email delivery succeeded")
return false, nil return false, nil
} }
@@ -202,7 +204,7 @@ func (b *Bot) sendAutoreply(roomID id.RoomID, threadID id.EventID) {
} }
evt := &event.Event{ evt := &event.Event{
ID: threadID + "-autoreply", ID: id.EventID(fmt.Sprintf("%s-autoreply-%s", threadID, time.Now().UTC().Format("20060102T150405Z"))),
RoomID: roomID, RoomID: roomID,
Content: event.Content{ Content: event.Content{
Parsed: &event.MessageEventContent{ Parsed: &event.MessageEventContent{
@@ -256,17 +258,17 @@ func (b *Bot) sendAutoreply(roomID id.RoomID, threadID id.EventID) {
queued, err = b.Sendmail(evt.ID, meta.From, to, data) queued, err = b.Sendmail(evt.ID, meta.From, to, data)
if queued { if queued {
b.log.Info().Err(err).Str("from", meta.From).Str("to", to).Msg("email has been queued") b.log.Info().Err(err).Str("from", meta.From).Str("to", to).Msg("email has been queued")
b.saveSentMetadata(ctx, queued, meta.ThreadID, recipients, eml, cfg, "Autoreply has been sent (queued)") b.saveSentMetadata(ctx, queued, meta.ThreadID, recipients, eml, cfg, "Autoreply has been sent to "+to+" (queued)")
continue continue
} }
if err != nil { if err != nil {
b.Error(ctx, "cannot send email: %v", err) b.Error(ctx, "cannot send email to %q: %v", to, err)
continue continue
} }
}
b.saveSentMetadata(ctx, queued, meta.ThreadID, recipients, eml, cfg, "Autoreply has been sent") b.saveSentMetadata(ctx, queued, meta.ThreadID, recipients, eml, cfg, "Autoreply has been sent to "+to)
}
} }
func (b *Bot) canReply(ctx context.Context) bool { func (b *Bot) canReply(ctx context.Context) bool {
@@ -345,12 +347,12 @@ func (b *Bot) SendEmailReply(ctx context.Context) {
} }
if err != nil { if err != nil {
b.Error(ctx, "cannot send email: %v", err) b.Error(ctx, "cannot send email to %q: %v", to, err)
continue continue
} }
}
b.saveSentMetadata(ctx, queued, meta.ThreadID, recipients, eml, cfg) b.saveSentMetadata(ctx, queued, meta.ThreadID, recipients, eml, cfg)
}
} }
type parentEmail struct { type parentEmail struct {
@@ -420,7 +422,7 @@ func (e *parentEmail) fixtofrom(newSenderMailbox string, domains []string) strin
func (e *parentEmail) calculateRecipients(from string, forwardedFrom []string) { func (e *parentEmail) calculateRecipients(from string, forwardedFrom []string) {
recipients := map[string]struct{}{} recipients := map[string]struct{}{}
recipients[e.From] = struct{}{} recipients[email.Address(e.From)] = struct{}{}
for _, addr := range strings.Split(email.Address(e.To), ",") { for _, addr := range strings.Split(email.Address(e.To), ",") {
recipients[addr] = struct{}{} recipients[addr] = struct{}{}
@@ -436,7 +438,7 @@ func (e *parentEmail) calculateRecipients(from string, forwardedFrom []string) {
rcpts := make([]string, 0, len(recipients)) rcpts := make([]string, 0, len(recipients))
for rcpt := range recipients { for rcpt := range recipients {
rcpts = append(rcpts, rcpt) rcpts = append(rcpts, email.Address(rcpt))
} }
e.Recipients = rcpts e.Recipients = rcpts
@@ -486,10 +488,10 @@ func (b *Bot) getParentEmail(evt *event.Event, newFromMailbox string) *parentEma
return parent return parent
} }
parent.From = linkpearl.EventField[string](&parentEvt.Content, eventFromKey) parent.From = email.Address(linkpearl.EventField[string](&parentEvt.Content, eventFromKey))
parent.To = linkpearl.EventField[string](&parentEvt.Content, eventToKey) parent.To = email.Address(linkpearl.EventField[string](&parentEvt.Content, eventToKey))
parent.CC = linkpearl.EventField[string](&parentEvt.Content, eventCcKey) parent.CC = email.Address(linkpearl.EventField[string](&parentEvt.Content, eventCcKey))
parent.RcptTo = linkpearl.EventField[string](&parentEvt.Content, eventRcptToKey) parent.RcptTo = email.Address(linkpearl.EventField[string](&parentEvt.Content, eventRcptToKey))
parent.InReplyTo = linkpearl.EventField[string](&parentEvt.Content, eventMessageIDkey) parent.InReplyTo = linkpearl.EventField[string](&parentEvt.Content, eventMessageIDkey)
parent.References = linkpearl.EventField[string](&parentEvt.Content, eventReferencesKey) parent.References = linkpearl.EventField[string](&parentEvt.Content, eventReferencesKey)
senderEmail := parent.fixtofrom(newFromMailbox, b.domains) senderEmail := parent.fixtofrom(newFromMailbox, b.domains)

View File

@@ -3,7 +3,6 @@ package bot
import ( import (
"context" "context"
"gitlab.com/etke.cc/go/mxidwc"
"maunium.net/go/mautrix" "maunium.net/go/mautrix"
"maunium.net/go/mautrix/event" "maunium.net/go/mautrix/event"
) )
@@ -33,7 +32,7 @@ func (b *Bot) initSync() {
// joinPermit is called by linkpearl when processing "invite" events and deciding if rooms should be auto-joined or not // joinPermit is called by linkpearl when processing "invite" events and deciding if rooms should be auto-joined or not
func (b *Bot) joinPermit(evt *event.Event) bool { func (b *Bot) joinPermit(evt *event.Event) bool {
if !mxidwc.Match(evt.Sender.String(), b.allowedUsers) { if !b.allowUsers(evt.Sender, evt.RoomID) {
b.log.Debug().Str("userID", evt.Sender.String()).Msg("Rejecting room invitation from unallowed user") b.log.Debug().Str("userID", evt.Sender.String()).Msg("Rejecting room invitation from unallowed user")
return false return false
} }

View File

@@ -55,7 +55,7 @@ func (s *incomingSession) Mail(from string, opts smtp.MailOptions) error {
s.ban(s.addr) s.ban(s.addr)
return ErrBanned return ErrBanned
} }
s.from = from s.from = email.Address(from)
s.log.Debug().Str("from", from).Any("options", opts).Msg("incoming mail") s.log.Debug().Str("from", from).Any("options", opts).Msg("incoming mail")
return nil return nil
} }