Skip to content

Commit eeccd4a

Browse files
committed
policyeval/antispam: handle federated_user_may_invite and MSC4311
1 parent 275b58a commit eeccd4a

File tree

2 files changed

+57
-8
lines changed

2 files changed

+57
-8
lines changed

cmd/meowlnir/antispam.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/rs/zerolog/hlog"
99
"go.mau.fi/util/exhttp"
1010
"maunium.net/go/mautrix"
11+
"maunium.net/go/mautrix/event"
1112
"maunium.net/go/mautrix/id"
1213
)
1314

@@ -17,6 +18,10 @@ type ReqUserMayInvite struct {
1718
Room id.RoomID `json:"room_id"`
1819
}
1920

21+
type ReqFederatedUserMayInvite struct {
22+
Event *event.Event `json:"event"`
23+
}
24+
2025
type ReqUserMayJoinRoom struct {
2126
UserID id.UserID `json:"user"`
2227
RoomID id.RoomID `json:"room"`
@@ -33,6 +38,8 @@ func (m *Meowlnir) PostCallback(w http.ResponseWriter, r *http.Request) {
3338
switch cbType {
3439
case "user_may_invite":
3540
m.PostUserMayInvite(w, r)
41+
case "federated_user_may_invite":
42+
m.PostFederatedUserMayInvite(w, r)
3643
case "accept_make_join":
3744
m.PostAcceptMakeJoin(w, r)
3845
case "user_may_join_room":
@@ -114,7 +121,31 @@ func (m *Meowlnir) PostUserMayInvite(w http.ResponseWriter, r *http.Request) {
114121
mautrix.MNotFound.WithMessage("Antispam configuration issue: policy list not found").Write(w)
115122
return
116123
}
117-
errResp := mgmtRoom.HandleUserMayInvite(r.Context(), req.Inviter, req.Invitee, req.Room)
124+
errResp := mgmtRoom.HandleUserMayInvite(r.Context(), req.Inviter, req.Invitee, req.Room, "")
125+
if errResp != nil {
126+
errResp.Write(w)
127+
} else {
128+
exhttp.WriteEmptyJSONResponse(w, http.StatusOK)
129+
}
130+
}
131+
132+
func (m *Meowlnir) PostFederatedUserMayInvite(w http.ResponseWriter, r *http.Request) {
133+
var req ReqFederatedUserMayInvite
134+
err := json.NewDecoder(r.Body).Decode(&req)
135+
if err != nil {
136+
hlog.FromRequest(r).Err(err).Msg("Failed to parse request body")
137+
mautrix.MNotJSON.WithMessage("Antispam request error: invalid JSON").Write(w)
138+
return
139+
}
140+
141+
m.MapLock.RLock()
142+
mgmtRoom, ok := m.EvaluatorByManagementRoom[id.RoomID(r.PathValue("policyListID"))]
143+
m.MapLock.RUnlock()
144+
if !ok {
145+
mautrix.MNotFound.WithMessage("Antispam configuration issue: policy list not found").Write(w)
146+
return
147+
}
148+
errResp := mgmtRoom.HandleFederatedUserMayInvite(r.Context(), req.Event)
118149
if errResp != nil {
119150
errResp.Write(w)
120151
} else {

policyeval/antispam.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,19 @@ type pendingInvite struct {
2323
Room id.RoomID
2424
}
2525

26-
func (pe *PolicyEvaluator) HandleUserMayInvite(ctx context.Context, inviter, invitee id.UserID, roomID id.RoomID) *mautrix.RespError {
26+
func (pe *PolicyEvaluator) HandleFederatedUserMayInvite(ctx context.Context, evt *event.Event) *mautrix.RespError {
27+
var roomCreator id.UserID
28+
for _, stateEvt := range evt.Unsigned.InviteRoomState {
29+
switch stateEvt.Type {
30+
case event.StateCreate:
31+
roomCreator = stateEvt.Sender
32+
}
33+
// TODO also do things like checking room name
34+
}
35+
return pe.HandleUserMayInvite(ctx, evt.Sender, id.UserID(evt.GetStateKey()), evt.RoomID, roomCreator)
36+
}
37+
38+
func (pe *PolicyEvaluator) HandleUserMayInvite(ctx context.Context, inviter, invitee id.UserID, roomID id.RoomID, roomCreator id.UserID) *mautrix.RespError {
2739
inviterServer := inviter.Homeserver()
2840
// We only care about federated invites.
2941
if inviterServer == pe.Bot.ServerName && !pe.FilterLocalInvites {
@@ -90,12 +102,18 @@ func (pe *PolicyEvaluator) HandleUserMayInvite(ctx context.Context, inviter, inv
90102
// Parsing room IDs is generally not allowed, but in this case,
91103
// if a room was created on a banned server, there's no reason to allow invites to it.
92104
_, _, roomServer := id.ParseCommonIdentifier(roomID)
93-
if rec = pe.Store.MatchServer(lists, roomServer).Recommendations().BanOrUnban; rec != nil && rec.Recommendation != event.PolicyRecommendationUnban {
94-
log.Debug().
95-
Str("policy_entity", rec.EntityOrHash()).
96-
Str("policy_reason", rec.Reason).
97-
Msg("Blocking invite to room on banned server")
98-
return ptr.Ptr(mautrix.MForbidden.WithMessage("Inviting users to this room is not allowed"))
105+
if roomServer == "" {
106+
// If the room ID has no server part, check the create event sender (MSC4311).
107+
roomServer = roomCreator.Homeserver()
108+
}
109+
if roomServer != "" {
110+
if rec = pe.Store.MatchServer(lists, roomServer).Recommendations().BanOrUnban; rec != nil && rec.Recommendation != event.PolicyRecommendationUnban {
111+
log.Debug().
112+
Str("policy_entity", rec.EntityOrHash()).
113+
Str("policy_reason", rec.Reason).
114+
Msg("Blocking invite to room on banned server")
115+
return ptr.Ptr(mautrix.MForbidden.WithMessage("Inviting users to this room is not allowed"))
116+
}
99117
}
100118

101119
rec = nil

0 commit comments

Comments
 (0)