Kick back joins with invalid authorising user IDs, use event from "event" key if returned in RespSendJoin

This commit is contained in:
Neil Alexander 2022-05-23 15:34:11 +01:00
parent 84c6c80b9f
commit c0a6932b1b
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
2 changed files with 36 additions and 2 deletions

View file

@ -209,10 +209,16 @@ func (r *FederationInternalAPI) performJoinUsingServer(
} }
r.statistics.ForServer(serverName).Success() r.statistics.ForServer(serverName).Success()
authEvents := respSendJoin.AuthEvents.UntrustedEvents(respMakeJoin.RoomVersion) // If the remote server returned an event in the "event" key of
// the send_join request then we should use that instead. It may
// contain signatures that we don't know about.
if respSendJoin.Event != nil {
event = respSendJoin.Event
}
// Sanity-check the join response to ensure that it has a create // Sanity-check the join response to ensure that it has a create
// event, that the room version is known, etc. // event, that the room version is known, etc.
authEvents := respSendJoin.AuthEvents.UntrustedEvents(respMakeJoin.RoomVersion)
if err = sanityCheckAuthChain(authEvents); err != nil { if err = sanityCheckAuthChain(authEvents); err != nil {
return fmt.Errorf("sanityCheckAuthChain: %w", err) return fmt.Errorf("sanityCheckAuthChain: %w", err)
} }

View file

@ -15,6 +15,7 @@
package routing package routing
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"sort" "sort"
@ -174,6 +175,7 @@ func MakeJoin(
// SendJoin implements the /send_join API // SendJoin implements the /send_join API
// The make-join send-join dance makes much more sense as a single // The make-join send-join dance makes much more sense as a single
// flow so the cyclomatic complexity is high: // flow so the cyclomatic complexity is high:
// nolint:gocyclo
func SendJoin( func SendJoin(
httpReq *http.Request, httpReq *http.Request,
request *gomatrixserverlib.FederationRequest, request *gomatrixserverlib.FederationRequest,
@ -327,8 +329,34 @@ func SendJoin(
} }
} }
// If the membership content contains a user ID for a server that is not
// ours then we should kick it back.
var memberContent gomatrixserverlib.MemberContent
if err := json.Unmarshal(event.Content(), &memberContent); err != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.BadJSON(err.Error()),
}
}
if memberContent.AuthorisedVia != "" {
_, domain, err := gomatrixserverlib.SplitID('@', memberContent.AuthorisedVia)
if err != nil {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.BadJSON(fmt.Sprintf("The authorising username %q is invalid.", memberContent.AuthorisedVia)),
}
}
if domain != cfg.Matrix.ServerName {
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.BadJSON(fmt.Sprintf("The authorising username %q does not belong to this server.", memberContent.AuthorisedVia)),
}
}
}
// Sign the membership event. This is required for restricted joins to work // Sign the membership event. This is required for restricted joins to work
// in the case that the authorised via user is one of our own users. // in the case that the authorised via user is one of our own users. It also
// doesn't hurt to do it even if it isn't a restricted join.
signed := event.Sign( signed := event.Sign(
string(cfg.Matrix.ServerName), string(cfg.Matrix.ServerName),
cfg.Matrix.KeyID, cfg.Matrix.KeyID,