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

Add MXIDMapping for pseudoID rooms #3112

Merged
merged 24 commits into from
Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d63685a
Add MXIDMapping for pseudoID rooms, also sign with the pseudoIDKey
S7evinK Jun 13, 2023
781bd80
Update GMSL
S7evinK Jun 13, 2023
50615c7
Sign MXIDMapping for join events
S7evinK Jun 14, 2023
34ab4d1
Get signing identity depending on the room version
S7evinK Jun 14, 2023
93a2687
Merge branch 'main' of github.com:matrix-org/dendrite into s7evink/mx…
S7evinK Jun 14, 2023
fd99925
Correctly resolve userID
S7evinK Jun 15, 2023
b655017
Workaround problem with senderID/userID
S7evinK Jun 15, 2023
8f967e5
Partially working pseudo IDs
S7evinK Jun 15, 2023
7f41a6a
Update GMSL
S7evinK Jun 15, 2023
07960a5
Cleanup, fix test
S7evinK Jun 15, 2023
e6fd65b
Fix empty senderID
S7evinK Jun 15, 2023
4406c85
Merge main, fix issues
S7evinK Jun 15, 2023
0f30550
Merge branch 'main' of github.com:matrix-org/dendrite into s7evink/mx…
S7evinK Jun 15, 2023
b4d5c83
Update test
S7evinK Jun 15, 2023
31609d6
Replace senderID with userID in powerlevel events, workaround invites
S7evinK Jun 15, 2023
708e950
Update GMSL
S7evinK Jun 15, 2023
75ffbc6
Linter
S7evinK Jun 15, 2023
45003cc
Also set the prev_content, if present
S7evinK Jun 16, 2023
f2e9815
Change the powerlevels from userID -> senderID
S7evinK Jun 16, 2023
52c888c
Update GMSL
S7evinK Jun 16, 2023
a33ef5b
Merge branch 'main' of github.com:matrix-org/dendrite into s7evink/mx…
S7evinK Jun 28, 2023
88b0f6a
We don't need to sign these events (correctly)?
S7evinK Jun 28, 2023
6697f43
Move creation of pseudo ID keys to the roomserver
S7evinK Jun 28, 2023
86f217f
Make it possible to join pseudo ID rooms (#3119)
S7evinK Jun 28, 2023
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
18 changes: 9 additions & 9 deletions clientapi/routing/membership.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ import (
"time"

"github.com/getsentry/sentry-go"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/matrix-org/gomatrixserverlib/spec"

appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
"github.com/matrix-org/dendrite/clientapi/httputil"
Expand All @@ -36,6 +32,9 @@ import (
"github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/dendrite/setup/config"
userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/matrix-org/gomatrixserverlib/spec"

"github.com/matrix-org/util"
)
Expand Down Expand Up @@ -433,11 +432,6 @@ func buildMembershipEvent(
return nil, err
}

identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain())
if err != nil {
return nil, err
}

userID, err := spec.NewUserID(device.UserID, true)
if err != nil {
return nil, err
Expand All @@ -459,6 +453,12 @@ func buildMembershipEvent(
if err != nil {
return nil, err
}

identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *userID)
if err != nil {
return nil, err
}

return buildMembershipEventDirect(ctx, targetSenderID, reason, profile.DisplayName, profile.AvatarURL,
senderID, device.UserDomain(), membership, roomID, isDirect, identity.KeyID, identity.PrivateKey, evTime, rsAPI)
}
Expand Down
20 changes: 12 additions & 8 deletions clientapi/routing/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func SetAvatarURL(
}
}

response, err := updateProfile(req.Context(), rsAPI, device, profile, userID, cfg, evTime)
response, err := updateProfile(req.Context(), rsAPI, device, profile, userID, evTime)
if err != nil {
return response
}
Expand Down Expand Up @@ -246,7 +246,7 @@ func SetDisplayName(
}
}

response, err := updateProfile(req.Context(), rsAPI, device, profile, userID, cfg, evTime)
response, err := updateProfile(req.Context(), rsAPI, device, profile, userID, evTime)
if err != nil {
return response
}
Expand All @@ -260,7 +260,7 @@ func SetDisplayName(
func updateProfile(
ctx context.Context, rsAPI api.ClientRoomserverAPI, device *userapi.Device,
profile *authtypes.Profile,
userID string, cfg *config.ClientAPI, evTime time.Time,
userID string, evTime time.Time,
) (util.JSONResponse, error) {
var res api.QueryRoomsForUserResponse
err := rsAPI.QueryRoomsForUser(ctx, &api.QueryRoomsForUserRequest{
Expand All @@ -285,7 +285,7 @@ func updateProfile(
}

events, err := buildMembershipEvents(
ctx, device, res.RoomIDs, *profile, userID, cfg, evTime, rsAPI,
ctx, res.RoomIDs, *profile, userID, evTime, rsAPI,
)
switch e := err.(type) {
case nil:
Expand Down Expand Up @@ -356,9 +356,8 @@ func getProfile(

func buildMembershipEvents(
ctx context.Context,
device *userapi.Device,
roomIDs []string,
newProfile authtypes.Profile, userID string, cfg *config.ClientAPI,
newProfile authtypes.Profile, userID string,
evTime time.Time, rsAPI api.ClientRoomserverAPI,
) ([]*types.HeaderedEvent, error) {
evs := []*types.HeaderedEvent{}
Expand Down Expand Up @@ -395,12 +394,17 @@ func buildMembershipEvents(
return nil, err
}

identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain())
user, err := spec.NewUserID(userID, true)
if err != nil {
return nil, err
}

event, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, evTime, rsAPI, nil)
identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *user)
if err != nil {
return nil, err
}

event, err := eventutil.QueryAndBuildEvent(ctx, &proto, &identity, evTime, rsAPI, nil)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions clientapi/routing/redaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func SendRedaction(
}
}

identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain())
identity, err := rsAPI.SigningIdentityFor(req.Context(), *validRoomID, *deviceUserID)
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
Expand All @@ -159,7 +159,7 @@ func SendRedaction(
}

var queryRes roomserverAPI.QueryLatestEventsAndStateResponse
e, err := eventutil.QueryAndBuildEvent(req.Context(), &proto, identity, time.Now(), rsAPI, &queryRes)
e, err := eventutil.QueryAndBuildEvent(req.Context(), &proto, &identity, time.Now(), rsAPI, &queryRes)
if errors.Is(err, eventutil.ErrRoomNoExists{}) {
return util.JSONResponse{
Code: http.StatusNotFound,
Expand Down
53 changes: 43 additions & 10 deletions clientapi/routing/sendevent.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,18 @@ import (
"sync"
"time"

"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"

"github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/internal/eventutil"
"github.com/matrix-org/dendrite/internal/transactions"
"github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/roomserver/types"
"github.com/matrix-org/dendrite/setup/config"
userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
"github.com/prometheus/client_golang/prometheus"
"github.com/sirupsen/logrus"
)

// http://matrix.org/docs/spec/client_server/r0.2.0.html#put-matrix-client-r0-rooms-roomid-send-eventtype-txnid
Expand Down Expand Up @@ -68,6 +67,8 @@ var sendEventDuration = prometheus.NewHistogramVec(
// /rooms/{roomID}/send/{eventType}
// /rooms/{roomID}/send/{eventType}/{txnID}
// /rooms/{roomID}/state/{eventType}/{stateKey}
//
// nolint: gocyclo
func SendEvent(
req *http.Request,
device *userapi.Device,
Expand Down Expand Up @@ -121,6 +122,17 @@ func SendEvent(
delete(r, "join_authorised_via_users_server")
}

// for power level events we need to replace the userID with the pseudoID
devonh marked this conversation as resolved.
Show resolved Hide resolved
if roomVersion == gomatrixserverlib.RoomVersionPseudoIDs && eventType == spec.MRoomPowerLevels {
err = updatePowerLevels(req, r, roomID, rsAPI)
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{Err: err.Error()},
}
}
}

evTime, err := httputil.ParseTSParam(req)
if err != nil {
return util.JSONResponse{
Expand All @@ -129,7 +141,7 @@ func SendEvent(
}
}

e, resErr := generateSendEvent(req.Context(), r, device, roomID, eventType, stateKey, cfg, rsAPI, evTime)
e, resErr := generateSendEvent(req.Context(), r, device, roomID, eventType, stateKey, rsAPI, evTime)
if resErr != nil {
return *resErr
}
Expand Down Expand Up @@ -225,6 +237,28 @@ func SendEvent(
return res
}

func updatePowerLevels(req *http.Request, r map[string]interface{}, roomID string, rsAPI api.ClientRoomserverAPI) error {
userMap := r["users"].(map[string]interface{})
validRoomID, err := spec.NewRoomID(roomID)
if err != nil {
return err
}
for user, level := range userMap {
uID, err := spec.NewUserID(user, true)
if err != nil {
continue // we're modifying the map in place, so we're going to have invalid userIDs after the first iteration
}
senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), *validRoomID, *uID)
if err != nil {
return err
}
userMap[string(senderID)] = level
delete(userMap, user)
}
r["users"] = userMap
return nil
}

// stateEqual compares the new and the existing state event content. If they are equal, returns a *util.JSONResponse
// with the existing event_id, making this an idempotent request.
func stateEqual(ctx context.Context, rsAPI api.ClientRoomserverAPI, eventType, stateKey, roomID string, newContent map[string]interface{}) *util.JSONResponse {
Expand Down Expand Up @@ -261,7 +295,6 @@ func generateSendEvent(
r map[string]interface{},
device *userapi.Device,
roomID, eventType string, stateKey *string,
cfg *config.ClientAPI,
rsAPI api.ClientRoomserverAPI,
evTime time.Time,
) (gomatrixserverlib.PDU, *util.JSONResponse) {
Expand Down Expand Up @@ -304,7 +337,7 @@ func generateSendEvent(
}
}

identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain())
identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *fullUserID)
if err != nil {
return nil, &util.JSONResponse{
Code: http.StatusInternalServerError,
Expand All @@ -313,7 +346,7 @@ func generateSendEvent(
}

var queryRes api.QueryLatestEventsAndStateResponse
e, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, evTime, rsAPI, &queryRes)
e, err := eventutil.QueryAndBuildEvent(ctx, &proto, &identity, evTime, rsAPI, &queryRes)
switch specificErr := err.(type) {
case nil:
case eventutil.ErrRoomNoExists:
Expand Down
4 changes: 2 additions & 2 deletions clientapi/routing/server_notices.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ func SendServerNotice(
"body": r.Content.Body,
"msgtype": r.Content.MsgType,
}
e, resErr := generateSendEvent(ctx, request, senderDevice, roomID, "m.room.message", nil, cfgClient, rsAPI, time.Now())
e, resErr := generateSendEvent(ctx, request, senderDevice, roomID, "m.room.message", nil, rsAPI, time.Now())
if resErr != nil {
logrus.Errorf("failed to send message: %+v", resErr)
return *resErr
Expand Down Expand Up @@ -350,7 +350,7 @@ func getSenderDevice(
if len(deviceRes.Devices) > 0 {
// If there were changes to the profile, create a new membership event
if displayNameChanged || avatarChanged {
_, err = updateProfile(ctx, rsAPI, &deviceRes.Devices[0], profile, accRes.Account.UserID, cfg, time.Now())
_, err = updateProfile(ctx, rsAPI, &deviceRes.Devices[0], profile, accRes.Account.UserID, time.Now())
if err != nil {
return nil, err
}
Expand Down
15 changes: 10 additions & 5 deletions federationapi/consumers/roomserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func (s *OutputRoomEventConsumer) processMessage(ore api.OutputNewRoomEvent, rew
evs[i] = addsStateEvents[i].PDU
}

addsJoinedHosts, err := JoinedHostsFromEvents(evs)
addsJoinedHosts, err := JoinedHostsFromEvents(s.ctx, evs, s.rsAPI)
if err != nil {
return err
}
Expand Down Expand Up @@ -345,7 +345,7 @@ func (s *OutputRoomEventConsumer) joinedHostsAtEvent(
return nil, err
}

combinedAddsJoinedHosts, err := JoinedHostsFromEvents(combinedAddsEvents)
combinedAddsJoinedHosts, err := JoinedHostsFromEvents(s.ctx, combinedAddsEvents, s.rsAPI)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -394,7 +394,7 @@ func (s *OutputRoomEventConsumer) joinedHostsAtEvent(
// JoinedHostsFromEvents turns a list of state events into a list of joined hosts.
// This errors if one of the events was invalid.
// It should be impossible for an invalid event to get this far in the pipeline.
func JoinedHostsFromEvents(evs []gomatrixserverlib.PDU) ([]types.JoinedHost, error) {
func JoinedHostsFromEvents(ctx context.Context, evs []gomatrixserverlib.PDU, rsAPI api.FederationRoomserverAPI) ([]types.JoinedHost, error) {
var joinedHosts []types.JoinedHost
for _, ev := range evs {
if ev.Type() != "m.room.member" || ev.StateKey() == nil {
Expand All @@ -407,12 +407,17 @@ func JoinedHostsFromEvents(evs []gomatrixserverlib.PDU) ([]types.JoinedHost, err
if membership != spec.Join {
continue
}
_, serverName, err := gomatrixserverlib.SplitID('@', *ev.StateKey())
validRoomID, err := spec.NewRoomID(ev.RoomID())
if err != nil {
return nil, err
}
userID, err := rsAPI.QueryUserIDForSender(ctx, *validRoomID, spec.SenderID(*ev.StateKey()))
if err != nil {
return nil, err
}

joinedHosts = append(joinedHosts, types.JoinedHost{
MemberEventID: ev.EventID(), ServerName: serverName,
MemberEventID: ev.EventID(), ServerName: userID.Domain(),
})
}
return joinedHosts, nil
Expand Down
22 changes: 17 additions & 5 deletions federationapi/internal/perform.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package internal

import (
"context"
"crypto/ed25519"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -170,13 +171,24 @@ func (r *FederationInternalAPI) performJoinUsingServer(
UserIDQuerier: func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
return r.rsAPI.QueryUserIDForSender(ctx, roomID, senderID)
},
SenderIDCreator: func(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (spec.SenderID, error) {
GetOrCreateSenderID: func(ctx context.Context, userID spec.UserID, roomID spec.RoomID, roomVersion string) (spec.SenderID, ed25519.PrivateKey, error) {
// assign a roomNID, otherwise we can't create a private key for the user
_, nidErr := r.rsAPI.AssignRoomNID(ctx, roomID, gomatrixserverlib.RoomVersion(roomVersion))
if nidErr != nil {
return "", nil, nidErr
}
key, keyErr := r.rsAPI.GetOrCreateUserRoomPrivateKey(ctx, userID, roomID)
if keyErr != nil {
return "", keyErr
return "", nil, keyErr
}

return spec.SenderID(spec.Base64Bytes(key).Encode()), nil
return spec.SenderIDFromPseudoIDKey(key), key, nil
},
StoreSenderIDFromPublicID: func(ctx context.Context, senderID spec.SenderID, userIDRaw string, roomID spec.RoomID) error {
storeUserID, userErr := spec.NewUserID(userIDRaw, true)
if userErr != nil {
return userErr
}
return r.rsAPI.StoreUserRoomPublicKey(ctx, senderID, *storeUserID, roomID)
},
}
response, joinErr := gomatrixserverlib.PerformJoin(ctx, r, joinInput)
Expand All @@ -200,7 +212,7 @@ func (r *FederationInternalAPI) performJoinUsingServer(
// joining a room, waiting for 200 OK then changing device keys and have those keys not be sent
// to other servers (this was a cause of a flakey sytest "Local device key changes get to remote servers")
// The events are trusted now as we performed auth checks above.
joinedHosts, err := consumers.JoinedHostsFromEvents(response.StateSnapshot.GetStateEvents().TrustedEvents(response.JoinEvent.Version(), false))
joinedHosts, err := consumers.JoinedHostsFromEvents(ctx, response.StateSnapshot.GetStateEvents().TrustedEvents(response.JoinEvent.Version(), false), r.rsAPI)
if err != nil {
return fmt.Errorf("JoinedHostsFromEvents: failed to get joined hosts: %s", err)
}
Expand Down
12 changes: 12 additions & 0 deletions federationapi/routing/join.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package routing

import (
"context"
"fmt"
"net/http"
"sort"
Expand Down Expand Up @@ -107,6 +108,10 @@ func MakeJoin(
}
}

if senderID == "" {
senderID = spec.SenderID(userID.String())
}

input := gomatrixserverlib.HandleMakeJoinInput{
Context: httpReq.Context(),
UserID: userID,
Expand Down Expand Up @@ -218,6 +223,13 @@ func SendJoin(
UserIDQuerier: func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
return rsAPI.QueryUserIDForSender(httpReq.Context(), roomID, senderID)
},
StoreSenderIDFromPublicID: func(ctx context.Context, senderID spec.SenderID, userIDRaw string, roomID spec.RoomID) error {
userID, userErr := spec.NewUserID(userIDRaw, true)
if userErr != nil {
return userErr
}
return rsAPI.StoreUserRoomPublicKey(ctx, senderID, *userID, roomID)
},
}
response, joinErr := gomatrixserverlib.HandleSendJoin(input)
switch e := joinErr.(type) {
Expand Down
Loading
Loading