mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-26 00:03:09 -06:00
auth remote servers
This commit is contained in:
parent
dd063a2722
commit
d3451b1ab8
|
|
@ -123,9 +123,13 @@ type reqCtx struct {
|
|||
rsAPI roomserver.RoomserverInternalAPI
|
||||
db Database
|
||||
req *EventRelationshipRequest
|
||||
fsAPI fs.FederationSenderInternalAPI
|
||||
userID string
|
||||
authorisedRoomIDs map[string]bool // events from these rooms can be returned
|
||||
|
||||
// federated request args
|
||||
isFederatedRequest bool
|
||||
serverName gomatrixserverlib.ServerName
|
||||
fsAPI fs.FederationSenderInternalAPI
|
||||
}
|
||||
|
||||
func eventRelationshipHandler(db Database, rsAPI roomserver.RoomserverInternalAPI) func(*http.Request, *userapi.Device) util.JSONResponse {
|
||||
|
|
@ -172,11 +176,12 @@ func federatedEventRelationship(
|
|||
rc := reqCtx{
|
||||
ctx: ctx,
|
||||
req: relation,
|
||||
userID: string(fedReq.Origin()),
|
||||
rsAPI: rsAPI,
|
||||
isFederatedRequest: true,
|
||||
db: db,
|
||||
// federation args
|
||||
isFederatedRequest: true,
|
||||
fsAPI: fsAPI,
|
||||
serverName: fedReq.Origin(),
|
||||
}
|
||||
res, resErr := rc.process()
|
||||
if resErr != nil {
|
||||
|
|
@ -193,9 +198,8 @@ func (rc *reqCtx) process() (*EventRelationshipResponse, *util.JSONResponse) {
|
|||
var res EventRelationshipResponse
|
||||
var returnEvents []*gomatrixserverlib.HeaderedEvent
|
||||
// Can the user see (according to history visibility) event_id? If no, reject the request, else continue.
|
||||
// We should have the event being referenced so don't give any claimed room ID / servers
|
||||
event := rc.getEventIfVisible(rc.req.EventID, "", nil)
|
||||
if event == nil {
|
||||
event := rc.getLocalEvent(rc.req.EventID)
|
||||
if event == nil || !rc.authorisedToSeeEvent(event) {
|
||||
return nil, &util.JSONResponse{
|
||||
Code: 403,
|
||||
JSON: jsonerror.Forbidden("Event does not exist or you are not authorised to see it"),
|
||||
|
|
@ -245,13 +249,12 @@ func (rc *reqCtx) process() (*EventRelationshipResponse, *util.JSONResponse) {
|
|||
|
||||
// If include_parent: true and there is a valid m.relationship field in the event,
|
||||
// retrieve the referenced event. Apply history visibility check to that event and if it passes, add it to the response array.
|
||||
func (rc *reqCtx) includeParent(event *gomatrixserverlib.HeaderedEvent) (parent *gomatrixserverlib.HeaderedEvent) {
|
||||
parentID, _, _ := parentChildEventIDs(event)
|
||||
func (rc *reqCtx) includeParent(childEvent *gomatrixserverlib.HeaderedEvent) (parent *gomatrixserverlib.HeaderedEvent) {
|
||||
parentID, _, _ := parentChildEventIDs(childEvent)
|
||||
if parentID == "" {
|
||||
return nil
|
||||
}
|
||||
claimedRoomID, claimedServers := roomIDAndServers(event)
|
||||
return rc.getEventIfVisible(parentID, claimedRoomID, claimedServers)
|
||||
return rc.getLocalEventIfVisible(parentID)
|
||||
}
|
||||
|
||||
// If include_children: true, lookup all events which have event_id as an m.relationship
|
||||
|
|
@ -266,8 +269,7 @@ func (rc *reqCtx) includeChildren(db Database, parentID string, limit int, recen
|
|||
}
|
||||
var childEvents []*gomatrixserverlib.HeaderedEvent
|
||||
for _, child := range children {
|
||||
// in order for us to even know about the children the server must be joined to those rooms, hence pass no claimed room ID or servers.
|
||||
childEvent := rc.getEventIfVisible(child.EventID, "", nil)
|
||||
childEvent := rc.getLocalEventIfVisible(child.EventID)
|
||||
if childEvent != nil {
|
||||
childEvents = append(childEvents, childEvent)
|
||||
}
|
||||
|
|
@ -306,7 +308,7 @@ func walkThread(
|
|||
|
||||
// Process the event.
|
||||
// TODO: Include edge information: room ID and servers
|
||||
event := rc.getEventIfVisible(wi.EventID, "", nil)
|
||||
event := rc.getLocalEventIfVisible(wi.EventID)
|
||||
if event != nil {
|
||||
result = append(result, event)
|
||||
}
|
||||
|
|
@ -341,77 +343,101 @@ func (rc *reqCtx) MSC2836EventRelationships(eventID string, srv gomatrixserverli
|
|||
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// getEventIfVisible returns the event if it is visible to the user. Does not perform any federated requests.
|
||||
// getEvent returns the event, retrieving it if necessary from a remote server.
|
||||
func (rc *reqCtx) getEventIfVisible(eventID string, claimedRoomID string, claimedServers []string) *gomatrixserverlib.HeaderedEvent {
|
||||
event, joinedToRoom := getEventIfVisible(rc.ctx, rc.rsAPI, eventID, rc.userID)
|
||||
if event != nil && joinedToRoom {
|
||||
// TODO: getRemoteEventIfVisible: if event ID is unknown, blindly attempt to join (which room? Origin, via who?) then hit /event_relationships.
|
||||
|
||||
// authorisedToSeeEvent authenticates that the user or server is allowed to see this event. Returns true if allowed to
|
||||
// see this request.
|
||||
func (rc *reqCtx) authorisedToSeeEvent(event *gomatrixserverlib.HeaderedEvent) bool {
|
||||
authorised, ok := rc.authorisedRoomIDs[event.RoomID()]
|
||||
if ok {
|
||||
return authorised
|
||||
}
|
||||
if rc.isFederatedRequest {
|
||||
// make sure the server is in this room
|
||||
var res fs.QueryJoinedHostServerNamesInRoomResponse
|
||||
err := rc.fsAPI.QueryJoinedHostServerNamesInRoom(rc.ctx, &fs.QueryJoinedHostServerNamesInRoomRequest{
|
||||
RoomID: event.RoomID(),
|
||||
}, &res)
|
||||
if err != nil {
|
||||
util.GetLogger(rc.ctx).WithError(err).Error("authenticateEvent: failed to QueryJoinedHostServerNamesInRoom")
|
||||
return false
|
||||
}
|
||||
for _, srv := range res.ServerNames {
|
||||
if srv == rc.serverName {
|
||||
rc.authorisedRoomIDs[event.RoomID()] = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
// make sure the user is in this room
|
||||
joinedToRoom, err := rc.allowedToSeeEvent(event.RoomID(), rc.userID)
|
||||
if err != nil || !joinedToRoom {
|
||||
return false
|
||||
}
|
||||
rc.authorisedRoomIDs[event.RoomID()] = true
|
||||
return true
|
||||
}
|
||||
|
||||
// getLocalEventIfVisible returns the event for the event ID given, by trying to auto-join rooms if not authorised
|
||||
func (rc *reqCtx) getLocalEventIfVisible(eventID string) *gomatrixserverlib.HeaderedEvent {
|
||||
event := rc.getLocalEvent(eventID)
|
||||
if event == nil {
|
||||
return nil
|
||||
}
|
||||
if rc.authorisedToSeeEvent(event) {
|
||||
return event
|
||||
}
|
||||
// either we don't have the event or we aren't joined to the room, regardless we should try joining if auto join is enabled
|
||||
if !rc.req.AutoJoin {
|
||||
return nil
|
||||
}
|
||||
// if we're doing this on behalf of a random server don't auto-join rooms regardless of what the request says
|
||||
if rc.isFederatedRequest {
|
||||
return nil
|
||||
}
|
||||
roomID := claimedRoomID
|
||||
var servers []gomatrixserverlib.ServerName
|
||||
if event != nil {
|
||||
roomID = event.RoomID()
|
||||
}
|
||||
for _, s := range claimedServers {
|
||||
servers = append(servers, gomatrixserverlib.ServerName(s))
|
||||
}
|
||||
if !rc.isFederatedRequest && rc.req.AutoJoin {
|
||||
// attempt to join the room then recheck auth, but only for local users
|
||||
var joinRes roomserver.PerformJoinResponse
|
||||
rc.rsAPI.PerformJoin(rc.ctx, &roomserver.PerformJoinRequest{
|
||||
UserID: rc.userID,
|
||||
Content: map[string]interface{}{},
|
||||
RoomIDOrAlias: roomID,
|
||||
ServerNames: servers,
|
||||
RoomIDOrAlias: event.RoomID(),
|
||||
}, &joinRes)
|
||||
if joinRes.Error != nil {
|
||||
util.GetLogger(rc.ctx).WithError(joinRes.Error).WithField("room_id", roomID).Error("Failed to auto-join room")
|
||||
util.GetLogger(rc.ctx).WithError(joinRes.Error).WithField("room_id", event.RoomID()).Error("Failed to auto-join room")
|
||||
return nil
|
||||
}
|
||||
if event != nil {
|
||||
delete(rc.authorisedRoomIDs, event.RoomID())
|
||||
if rc.authorisedToSeeEvent(event) {
|
||||
return event
|
||||
}
|
||||
// TODO: hit /event_relationships on the server we joined via
|
||||
util.GetLogger(rc.ctx).Infof("joined room but need to fetch event TODO")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getEventIfVisible(ctx context.Context, rsAPI roomserver.RoomserverInternalAPI, eventID, userID string) (*gomatrixserverlib.HeaderedEvent, bool) {
|
||||
var queryEventsRes roomserver.QueryEventsByIDResponse
|
||||
err := rsAPI.QueryEventsByID(ctx, &roomserver.QueryEventsByIDRequest{
|
||||
EventIDs: []string{eventID},
|
||||
}, &queryEventsRes)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("getEventIfVisible: failed to QueryEventsByID")
|
||||
return nil, false
|
||||
}
|
||||
if len(queryEventsRes.Events) == 0 {
|
||||
util.GetLogger(ctx).Infof("event does not exist")
|
||||
return nil, false // event does not exist
|
||||
}
|
||||
event := queryEventsRes.Events[0]
|
||||
|
||||
func (rc *reqCtx) allowedToSeeEvent(roomID, userID string) (bool, error) {
|
||||
// Allow events if the member is in the room
|
||||
// TODO: This does not honour history_visibility
|
||||
// TODO: This does not honour m.room.create content
|
||||
var queryMembershipRes roomserver.QueryMembershipForUserResponse
|
||||
err = rsAPI.QueryMembershipForUser(ctx, &roomserver.QueryMembershipForUserRequest{
|
||||
RoomID: event.RoomID(),
|
||||
err := rc.rsAPI.QueryMembershipForUser(rc.ctx, &roomserver.QueryMembershipForUserRequest{
|
||||
RoomID: roomID,
|
||||
UserID: userID,
|
||||
}, &queryMembershipRes)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("getEventIfVisible: failed to QueryMembershipForUser")
|
||||
return nil, false
|
||||
util.GetLogger(rc.ctx).WithError(err).Error("allowedToSeeEvent: failed to QueryMembershipForUser")
|
||||
return false, err
|
||||
}
|
||||
return event, queryMembershipRes.IsInRoom
|
||||
return queryMembershipRes.IsInRoom, nil
|
||||
}
|
||||
|
||||
func (rc *reqCtx) getLocalEvent(eventID string) *gomatrixserverlib.HeaderedEvent {
|
||||
var queryEventsRes roomserver.QueryEventsByIDResponse
|
||||
err := rc.rsAPI.QueryEventsByID(rc.ctx, &roomserver.QueryEventsByIDRequest{
|
||||
EventIDs: []string{eventID},
|
||||
}, &queryEventsRes)
|
||||
if err != nil {
|
||||
util.GetLogger(rc.ctx).WithError(err).Error("getLocalEvent: failed to QueryEventsByID")
|
||||
return nil
|
||||
}
|
||||
if len(queryEventsRes.Events) == 0 {
|
||||
util.GetLogger(rc.ctx).Infof("getLocalEvent: event does not exist")
|
||||
return nil // event does not exist
|
||||
}
|
||||
return queryEventsRes.Events[0]
|
||||
}
|
||||
|
||||
type walkInfo struct {
|
||||
|
|
|
|||
Loading…
Reference in a new issue