diff --git a/clientapi/routing/membership.go b/clientapi/routing/membership.go index cfdf6f2de..77f627eb2 100644 --- a/clientapi/routing/membership.go +++ b/clientapi/routing/membership.go @@ -188,6 +188,12 @@ func SendUnban( if err != nil { return util.ErrorResponse(err) } + if !queryRes.RoomExists { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: jsonerror.Forbidden("room does not exist"), + } + } // unban is only valid if the user is currently banned if queryRes.Membership != "ban" { return util.JSONResponse{ @@ -471,6 +477,12 @@ func SendForget( logger.WithError(err).Error("QueryMembershipForUser: could not query membership for user") return jsonerror.InternalServerError() } + if !membershipRes.RoomExists { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: jsonerror.Forbidden("room does not exist"), + } + } if membershipRes.IsInRoom { return util.JSONResponse{ Code: http.StatusBadRequest, diff --git a/clientapi/routing/state.go b/clientapi/routing/state.go index c6e9e91d0..12984c39a 100644 --- a/clientapi/routing/state.go +++ b/clientapi/routing/state.go @@ -56,6 +56,12 @@ func OnIncomingStateRequest(ctx context.Context, device *userapi.Device, rsAPI a util.GetLogger(ctx).WithError(err).Error("queryAPI.QueryLatestEventsAndState failed") return jsonerror.InternalServerError() } + if !stateRes.RoomExists { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: jsonerror.Forbidden("room does not exist"), + } + } // Look at the room state and see if we have a history visibility event // that marks the room as world-readable. If we don't then we assume that diff --git a/roomserver/api/query.go b/roomserver/api/query.go index ef2e6bb57..afafb87c3 100644 --- a/roomserver/api/query.go +++ b/roomserver/api/query.go @@ -122,6 +122,7 @@ type QueryMembershipForUserResponse struct { Membership string `json:"membership"` // True if the user asked to forget this room. IsRoomForgotten bool `json:"is_room_forgotten"` + RoomExists bool `json:"room_exists"` } // QueryMembershipsForRoomRequest is a request to QueryMembershipsForRoom diff --git a/roomserver/internal/query/query.go b/roomserver/internal/query/query.go index 5b33ec3c3..d25bdc378 100644 --- a/roomserver/internal/query/query.go +++ b/roomserver/internal/query/query.go @@ -169,8 +169,10 @@ func (r *Queryer) QueryMembershipForUser( return err } if info == nil { - return fmt.Errorf("QueryMembershipForUser: unknown room %s", request.RoomID) + response.RoomExists = false + return nil } + response.RoomExists = true membershipEventNID, stillInRoom, isRoomforgotten, err := r.DB.GetMembership(ctx, info.RoomNID, request.UserID) if err != nil { diff --git a/syncapi/routing/context.go b/syncapi/routing/context.go index 87cc2aae0..96438e184 100644 --- a/syncapi/routing/context.go +++ b/syncapi/routing/context.go @@ -73,6 +73,12 @@ func Context( logrus.WithError(err).Error("unable to query membership") return jsonerror.InternalServerError() } + if !membershipRes.RoomExists { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: jsonerror.Forbidden("room does not exist"), + } + } stateFilter := gomatrixserverlib.StateFilter{ Limit: 100, diff --git a/syncapi/routing/messages.go b/syncapi/routing/messages.go index b0c990ec0..e55c661d6 100644 --- a/syncapi/routing/messages.go +++ b/syncapi/routing/messages.go @@ -68,10 +68,16 @@ func OnIncomingMessagesRequest( var err error // check if the user has already forgotten about this room - isForgotten, err := checkIsRoomForgotten(req.Context(), roomID, device.UserID, rsAPI) + isForgotten, roomExists, err := checkIsRoomForgotten(req.Context(), roomID, device.UserID, rsAPI) if err != nil { return jsonerror.InternalServerError() } + if !roomExists { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: jsonerror.Forbidden("room does not exist"), + } + } if isForgotten { return util.JSONResponse{ @@ -244,17 +250,17 @@ func OnIncomingMessagesRequest( } } -func checkIsRoomForgotten(ctx context.Context, roomID, userID string, rsAPI api.SyncRoomserverAPI) (bool, error) { +func checkIsRoomForgotten(ctx context.Context, roomID, userID string, rsAPI api.SyncRoomserverAPI) (forgotten bool, exists bool, err error) { req := api.QueryMembershipForUserRequest{ RoomID: roomID, UserID: userID, } resp := api.QueryMembershipForUserResponse{} if err := rsAPI.QueryMembershipForUser(ctx, &req, &resp); err != nil { - return false, err + return false, false, err } - return resp.IsRoomForgotten, nil + return resp.IsRoomForgotten, resp.RoomExists, nil } // retrieveEvents retrieves events from the local database for a request on