Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various fixes in fetchAuthEvents #3447

Merged
merged 4 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 35 additions & 26 deletions roomserver/internal/input/input_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,27 @@ func (r *Inputer) processRoomEvent(
}
}

// Check that the auth events of the event are known.
// If they aren't then we will ask the federation API for them.
authEvents, _ := gomatrixserverlib.NewAuthEvents(nil)
knownEvents := map[string]*types.Event{}
if err = r.fetchAuthEvents(ctx, logger, roomInfo, virtualHost, headered, authEvents, knownEvents, serverRes.ServerNames); err != nil {
return fmt.Errorf("r.fetchAuthEvents: %w", err)
}

isRejected := false
var rejectionErr error

// Check if the event is allowed by its auth events. If it isn't then
// we consider the event to be "rejected" — it will still be persisted.
if err = gomatrixserverlib.Allowed(event, authEvents, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
return r.Queryer.QueryUserIDForSender(ctx, roomID, senderID)
}); err != nil {
isRejected = true
rejectionErr = err
logger.WithError(rejectionErr).Warnf("Event %s not allowed by auth events", event.EventID())
}

// At this point we are checking whether we know all of the prev events, and
// if we know the state before the prev events. This is necessary before we
// try to do `calculateAndSetState` on the event later, otherwise it will fail
Expand Down Expand Up @@ -283,24 +301,6 @@ func (r *Inputer) processRoomEvent(
}
}

// Check that the auth events of the event are known.
// If they aren't then we will ask the federation API for them.
authEvents, _ := gomatrixserverlib.NewAuthEvents(nil)
knownEvents := map[string]*types.Event{}
if err = r.fetchAuthEvents(ctx, logger, roomInfo, virtualHost, headered, authEvents, knownEvents, serverRes.ServerNames); err != nil {
return fmt.Errorf("r.fetchAuthEvents: %w", err)
}

// Check if the event is allowed by its auth events. If it isn't then
// we consider the event to be "rejected" — it will still be persisted.
if err = gomatrixserverlib.Allowed(event, authEvents, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
return r.Queryer.QueryUserIDForSender(ctx, roomID, senderID)
}); err != nil {
isRejected = true
rejectionErr = err
logger.WithError(rejectionErr).Warnf("Event %s not allowed by auth events", event.EventID())
}

// Accumulate the auth event NIDs.
authEventIDs := event.AuthEventIDs()
authEventNIDs := make([]types.EventNID, 0, len(authEventIDs))
Expand All @@ -323,7 +323,7 @@ func (r *Inputer) processRoomEvent(
)
}
}
} else {
} else if !knownEvents[authEventID].Rejected {
authEventNIDs = append(authEventNIDs, knownEvents[authEventID].EventNID)
}
}
Expand Down Expand Up @@ -704,15 +704,14 @@ func (r *Inputer) fetchAuthEvents(
}
ev := authEvents[0]

isRejected := false
if roomInfo != nil {
isRejected, err = r.DB.IsEventRejected(ctx, roomInfo.RoomNID, ev.EventID())
ev.Rejected, err = r.DB.IsEventRejected(ctx, roomInfo.RoomNID, ev.EventID())
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return fmt.Errorf("r.DB.IsEventRejected failed: %w", err)
}
}
known[authEventID] = &ev // don't take the pointer of the iterated event
if !isRejected {
if !ev.Rejected {
if err = auth.AddEvent(ev.PDU); err != nil {
return fmt.Errorf("auth.AddEvent: %w", err)
}
Expand Down Expand Up @@ -744,8 +743,13 @@ func (r *Inputer) fetchAuthEvents(
return fmt.Errorf("no servers provided event auth for event ID %q, tried servers %v", event.EventID(), servers)
}

// Start with a clean state and see if we can auth with what the remote
// server told us. Otherwise earlier topologically sorted events could
// fail to be authed by more recent referenced ones.
auth.Clear()

// Reuse these to reduce allocations.
authEventNIDs := make([]types.EventNID, 0, 5)
_authEventNIDs := [5]types.EventNID{}
isRejected := false
nextAuthEvent:
for _, authEvent := range gomatrixserverlib.ReverseTopologicalOrdering(
Expand All @@ -755,7 +759,11 @@ nextAuthEvent:
// If we already know about this event from the database then we don't
// need to store it again or do anything further with it, so just skip
// over it rather than wasting cycles.
if ev, ok := known[authEvent.EventID()]; ok && ev != nil {
if ev, ok := known[authEvent.EventID()]; ok && ev != nil && !ev.Rejected {
// Need to add to the auth set for the next event being processed.
if err := auth.AddEvent(authEvent); err != nil {
return fmt.Errorf("auth.AddEvent: %w", err)
}
continue nextAuthEvent
}

Expand All @@ -770,11 +778,11 @@ nextAuthEvent:

// In order to store the new auth event, we need to know its auth chain
// as NIDs for the `auth_event_nids` column. Let's see if we can find those.
authEventNIDs = authEventNIDs[:0]
authEventNIDs := _authEventNIDs[:0]
for _, eventID := range authEvent.AuthEventIDs() {
knownEvent, ok := known[eventID]
if !ok {
continue nextAuthEvent
return fmt.Errorf("auth event ID %s not known but should be", eventID)
}
authEventNIDs = append(authEventNIDs, knownEvent.EventNID)
}
Expand Down Expand Up @@ -821,6 +829,7 @@ nextAuthEvent:
// Now we know about this event, it was stored and the signatures were OK.
known[authEvent.EventID()] = &types.Event{
EventNID: eventNID,
Rejected: isRejected,
PDU: authEvent,
}
}
Expand Down
1 change: 1 addition & 0 deletions roomserver/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ func (s StateAtEventAndReferences) EventIDs() string {
// It is when performing bulk event lookup in the database.
type Event struct {
EventNID EventNID
Rejected bool
gomatrixserverlib.PDU
}

Expand Down
6 changes: 5 additions & 1 deletion sytest-blacklist
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ If a device list update goes missing, the server resyncs on the next one
Leaves are present in non-gapped incremental syncs

# We don't have any state to calculate m.room.guest_access when accepting invites
Guest users can accept invites to private rooms over federation
Guest users can accept invites to private rooms over federation

# Tests Synapse specific behavior
/state returns M_NOT_FOUND for an outlier
/state_ids returns M_NOT_FOUND for an outlier
2 changes: 0 additions & 2 deletions sytest-whitelist
Original file line number Diff line number Diff line change
Expand Up @@ -774,8 +774,6 @@ Remote user can backfill in a room with version 10
Can reject invites over federation for rooms with version 10
Can receive redactions from regular users over federation in room version 10
New federated private chats get full presence information (SYN-115)
/state returns M_NOT_FOUND for an outlier
/state_ids returns M_NOT_FOUND for an outlier
Outbound federation requests missing prev_events and then asks for /state_ids and resolves the state
Invited user can reject invite for empty room
Invited user can reject local invite after originator leaves
Expand Down
Loading