diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go index d46c69fb8..d686751aa 100644 --- a/clientapi/routing/routing.go +++ b/clientapi/routing/routing.go @@ -501,6 +501,7 @@ func Setup( ).Methods(http.MethodPost, http.MethodOptions) unstableMux.Handle("/org.matrix.msc4080/rooms/{roomID}/ban", httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse { + logrus.Info("Processing request to /org.matrix.msc4080/rooms/{roomID}/ban") vars, err := httputil.URLDecodeMapValues(mux.Vars(req)) if err != nil { return util.ErrorResponse(err) @@ -544,6 +545,7 @@ func Setup( ).Methods(http.MethodPost, http.MethodOptions) unstableMux.Handle("/org.matrix.msc4080/rooms/{roomID}/kick", httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse { + logrus.Info("Processing request to /org.matrix.msc4080/rooms/{roomID}/kick") vars, err := httputil.URLDecodeMapValues(mux.Vars(req)) if err != nil { return util.ErrorResponse(err) @@ -562,6 +564,7 @@ func Setup( ).Methods(http.MethodPost, http.MethodOptions) unstableMux.Handle("/org.matrix.msc4080/rooms/{roomID}/unban", httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse { + logrus.Info("Processing request to /org.matrix.msc4080/rooms/{roomID}/unban") vars, err := httputil.URLDecodeMapValues(mux.Vars(req)) if err != nil { return util.ErrorResponse(err) diff --git a/clientapi/routing/send_pdus.go b/clientapi/routing/send_pdus.go index 4f7a5e3ba..422882638 100644 --- a/clientapi/routing/send_pdus.go +++ b/clientapi/routing/send_pdus.go @@ -187,6 +187,33 @@ func SendPDUs( continue // NOTE: don't send this event on to the roomserver } } + case membership.Membership == spec.Invite: + stateKey := pdu.StateKey() + if stateKey == nil { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: spec.Forbidden("invalid state_key for membership event"), + } + } + userID, err := rsAPI.QueryUserIDForSender(req.Context(), pdu.RoomID(), spec.SenderID(*stateKey)) + if err != nil || userID == nil { + return util.JSONResponse{ + Code: http.StatusNotFound, + JSON: spec.NotFound("cannot find userID for invite event"), + } + } + if !cfg.Matrix.IsLocalServerName(spec.ServerName(userID.Domain())) { + inviteReq := roomserverAPI.PerformInviteRequestCryptoIDs{ + RoomID: pdu.RoomID().String(), + UserID: *userID, + InviteEvent: pdu, + } + err := rsAPI.PerformSendInviteCryptoIDs(req.Context(), &inviteReq) + if err != nil { + util.GetLogger(req.Context()).Errorf("Failed processing %s event (%s): %v", pdu.Type(), pdu.EventID(), err) + } + continue // NOTE: don't send this event on to the roomserver + } } } diff --git a/federationapi/api/api.go b/federationapi/api/api.go index 3be6b61bc..f61b1a343 100644 --- a/federationapi/api/api.go +++ b/federationapi/api/api.go @@ -66,6 +66,10 @@ type RoomserverFederationAPI interface { SendInvite(ctx context.Context, event gomatrixserverlib.PDU, strippedState []gomatrixserverlib.InviteStrippedState) (gomatrixserverlib.PDU, error) // Handle sending an invite to a remote server. SendInviteV3(ctx context.Context, event gomatrixserverlib.ProtoEvent, invitee spec.UserID, version gomatrixserverlib.RoomVersion, strippedState []gomatrixserverlib.InviteStrippedState) (gomatrixserverlib.PDU, error) + // Handle sending an invite to a remote server. + MakeInviteCryptoIDs(ctx context.Context, event gomatrixserverlib.ProtoEvent, invitee spec.UserID, version gomatrixserverlib.RoomVersion, strippedState []gomatrixserverlib.InviteStrippedState) (gomatrixserverlib.PDU, error) + // Handle sending an invite to a remote server. + SendInviteCryptoIDs(ctx context.Context, event gomatrixserverlib.PDU, invitee spec.UserID, version gomatrixserverlib.RoomVersion) error // Handle an instruction to peek a room on a remote server. PerformOutboundPeek(ctx context.Context, request *PerformOutboundPeekRequest, response *PerformOutboundPeekResponse) error // Query the server names of the joined hosts in a room. diff --git a/federationapi/internal/perform.go b/federationapi/internal/perform.go index 5625bc40b..4a2609eb2 100644 --- a/federationapi/internal/perform.go +++ b/federationapi/internal/perform.go @@ -964,6 +964,87 @@ func (r *FederationInternalAPI) SendInviteV3( return inviteEvent, nil } +// MakeInviteCryptoIDs implements api.FederationInternalAPI +func (r *FederationInternalAPI) MakeInviteCryptoIDs(ctx context.Context, event gomatrixserverlib.ProtoEvent, invitee spec.UserID, version gomatrixserverlib.RoomVersion, strippedState []gomatrixserverlib.InviteStrippedState) (gomatrixserverlib.PDU, error) { + validRoomID, err := spec.NewRoomID(event.RoomID) + if err != nil { + return nil, err + } + verImpl, err := gomatrixserverlib.GetRoomVersion(version) + if err != nil { + return nil, err + } + + inviter, err := r.rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(event.SenderID)) + if err != nil { + return nil, err + } + + // TODO (devon): This should be allowed via a relay. Currently only transactions + // can be sent to relays. Would need to extend relays to handle invites. + if !r.shouldAttemptDirectFederation(invitee.Domain()) { + return nil, fmt.Errorf("relay servers have no meaningful response for invite.") + } + + logrus.WithFields(logrus.Fields{ + "user_id": invitee.String(), + "room_id": event.RoomID, + "room_version": version, + "destination": invitee.Domain(), + }).Info("Sending /send_invite") + + inviteReq, err := fclient.NewInviteV3Request(event, version, strippedState) + if err != nil { + return nil, fmt.Errorf("gomatrixserverlib.NewInviteV3Request: %w", err) + } + + inviteRes, err := r.federation.MakeInviteCryptoIDs(ctx, inviter.Domain(), invitee.Domain(), inviteReq, invitee) + if err != nil { + return nil, fmt.Errorf("r.federation.SendInviteCryptoIDs: failed to send invite: %w", err) + } + + inviteEvent, err := verImpl.NewEventFromUntrustedJSON(inviteRes.Event) + if err != nil { + return nil, fmt.Errorf("r.federation.SendInviteCryptoIDs failed to decode event response: %w", err) + } + return inviteEvent, nil +} + +// SendInviteCryptoIDs implements api.FederationInternalAPI +func (r *FederationInternalAPI) SendInviteCryptoIDs(ctx context.Context, event gomatrixserverlib.PDU, invitee spec.UserID, version gomatrixserverlib.RoomVersion) error { + validRoomID := event.RoomID() + + inviter, err := r.rsAPI.QueryUserIDForSender(ctx, validRoomID, event.SenderID()) + if err != nil { + return err + } + + // TODO (devon): This should be allowed via a relay. Currently only transactions + // can be sent to relays. Would need to extend relays to handle invites. + if !r.shouldAttemptDirectFederation(invitee.Domain()) { + return fmt.Errorf("relay servers have no meaningful response for invite.") + } + + logrus.WithFields(logrus.Fields{ + "user_id": invitee.String(), + "room_id": event.RoomID, + "room_version": version, + "destination": invitee.Domain(), + }).Info("Sending /make_invite") + + inviteReq, err := fclient.NewSendInviteCryptoIDsRequest(event, version) + if err != nil { + return fmt.Errorf("gomatrixserverlib.NewInviteV3Request: %w", err) + } + + err = r.federation.SendInviteCryptoIDs(ctx, inviter.Domain(), invitee.Domain(), inviteReq, invitee) + if err != nil { + return fmt.Errorf("r.federation.SendInviteCryptoIDs: failed to send invite: %w", err) + } + + return nil +} + // PerformServersAlive implements api.FederationInternalAPI func (r *FederationInternalAPI) PerformBroadcastEDU( ctx context.Context, diff --git a/go.mod b/go.mod index 082f3e10b..67de90dfc 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/matrix-org/dendrite -replace github.com/matrix-org/gomatrixserverlib => ../../gomatrixserverlib/crypto-ids/ +//replace github.com/matrix-org/gomatrixserverlib => ../../gomatrixserverlib/crypto-ids/ + +//replace github.com/matrix-org/gomatrixserverlib => /src/gmsl/ require ( github.com/Arceliar/ironwood v0.0.0-20221025225125-45b4281814c2 @@ -24,7 +26,7 @@ require ( github.com/matrix-org/dugong v0.0.0-20210921133753-66e6b1c67e2e github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 - github.com/matrix-org/gomatrixserverlib v0.0.0-20230926165653-79fcff283fc4 + github.com/matrix-org/gomatrixserverlib v0.0.0-20231219232834-bbfb4a048862 github.com/matrix-org/pinecone v0.11.1-0.20230810010612-ea4c33717fd7 github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 github.com/mattn/go-sqlite3 v1.14.17 @@ -44,12 +46,12 @@ require ( github.com/uber/jaeger-lib v2.4.1+incompatible github.com/yggdrasil-network/yggdrasil-go v0.4.6 go.uber.org/atomic v1.10.0 - golang.org/x/crypto v0.13.0 + golang.org/x/crypto v0.17.0 golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819 golang.org/x/image v0.5.0 golang.org/x/mobile v0.0.0-20221020085226-b36e6246172e golang.org/x/sync v0.3.0 - golang.org/x/term v0.12.0 + golang.org/x/term v0.15.0 gopkg.in/h2non/bimg.v1 v1.1.9 gopkg.in/yaml.v2 v2.4.0 gotest.tools/v3 v3.4.0 @@ -126,8 +128,8 @@ require ( go.etcd.io/bbolt v1.3.6 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.14.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.12.0 // indirect google.golang.org/protobuf v1.30.0 // indirect diff --git a/go.sum b/go.sum index 7f0e98838..d249b2714 100644 --- a/go.sum +++ b/go.sum @@ -208,8 +208,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91 h1:s7fexw github.com/matrix-org/go-sqlite3-js v0.0.0-20220419092513-28aa791a1c91/go.mod h1:e+cg2q7C7yE5QnAXgzo512tgFh1RbQLC0+jozuegKgo= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8r4Fzarl4+Y3K5hjothkVW5z7T1dUM11U= github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230926165653-79fcff283fc4 h1:UuXfC7b29RBDfMdLmggeF3opu3XuGi8bNT9SKZtZc3I= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230926165653-79fcff283fc4/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20231219232834-bbfb4a048862 h1:Kuya3qas85ZvVVkuOpemwhgvdJbLojvwvt3xyJTp1dY= +github.com/matrix-org/gomatrixserverlib v0.0.0-20231219232834-bbfb4a048862/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= github.com/matrix-org/pinecone v0.11.1-0.20230810010612-ea4c33717fd7 h1:6t8kJr8i1/1I5nNttw6nn1ryQJgzVlBmSGgPiiaTdw4= github.com/matrix-org/pinecone v0.11.1-0.20230810010612-ea4c33717fd7/go.mod h1:ReWMS/LoVnOiRAdq9sNUC2NZnd1mZkMNB52QhpTRWjg= github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y= @@ -354,8 +354,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -418,19 +418,19 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/roomserver/api/api.go b/roomserver/api/api.go index d3813a5c1..7e112d2d3 100644 --- a/roomserver/api/api.go +++ b/roomserver/api/api.go @@ -247,6 +247,7 @@ type ClientRoomserverAPI interface { PerformInvite(ctx context.Context, req *PerformInviteRequest, cryptoIDs bool) (gomatrixserverlib.PDU, error) PerformJoin(ctx context.Context, req *PerformJoinRequest) (roomID string, joinedVia spec.ServerName, err error) PerformSendJoinCryptoIDs(ctx context.Context, req *PerformJoinRequestCryptoIDs) error + PerformSendInviteCryptoIDs(ctx context.Context, req *PerformInviteRequestCryptoIDs) error PerformJoinCryptoIDs(ctx context.Context, req *PerformJoinRequest) (join gomatrixserverlib.PDU, roomID string, version gomatrixserverlib.RoomVersion, serverName spec.ServerName, err error) PerformLeave(ctx context.Context, req *PerformLeaveRequest, res *PerformLeaveResponse, cryptoIDs bool) (gomatrixserverlib.PDU, error) PerformPublish(ctx context.Context, req *PerformPublishRequest) error diff --git a/roomserver/api/perform.go b/roomserver/api/perform.go index 973b6649d..7b97a324a 100644 --- a/roomserver/api/perform.go +++ b/roomserver/api/perform.go @@ -44,15 +44,21 @@ type PerformJoinRequest struct { } type PerformJoinRequestCryptoIDs struct { - RoomID string `json:"room_id"` - UserID string `json:"user_id"` - IsGuest bool `json:"is_guest"` - Content map[string]interface{} `json:"content"` - ServerNames []spec.ServerName `json:"server_names"` - Unsigned map[string]interface{} `json:"unsigned"` + RoomID string + UserID string + IsGuest bool + Content map[string]interface{} + ServerNames []spec.ServerName + Unsigned map[string]interface{} JoinEvent gomatrixserverlib.PDU } +type PerformInviteRequestCryptoIDs struct { + RoomID string + UserID spec.UserID + InviteEvent gomatrixserverlib.PDU +} + type PerformLeaveRequest struct { RoomID string Leaver spec.UserID diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index 1dee53af5..3b847d510 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -431,6 +431,23 @@ func (r *Joiner) PerformSendJoinCryptoIDs( return nil } +func (r *Joiner) PerformSendInviteCryptoIDs( + ctx context.Context, + req *rsAPI.PerformInviteRequestCryptoIDs, +) error { + logger := logrus.WithContext(ctx).WithFields(logrus.Fields{ + "room_id": req.RoomID, + "user_id": req.UserID, + }) + logger.Info("performing send invite") + err := r.FSAPI.SendInviteCryptoIDs(ctx, req.InviteEvent, req.UserID, req.InviteEvent.Version()) + if err != nil { + return err + } + + return nil +} + // PerformJoin handles joining matrix rooms, including over federation by talking to the federationapi. func (r *Joiner) PerformJoinCryptoIDs( ctx context.Context,