From 5c488d9146d7c802baf9184775b321f9b3cb69e2 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Mon, 12 Jun 2023 12:52:26 +0200 Subject: [PATCH 1/4] Create user room key if needed --- go.mod | 2 +- go.sum | 3 +++ roomserver/api/api.go | 4 +++ roomserver/internal/api.go | 21 ++++++++++++++++ .../internal/perform/perform_create_room.go | 25 ++++++++++++++++++- roomserver/internal/perform/perform_invite.go | 8 ++++++ roomserver/internal/perform/perform_join.go | 15 +++++++++++ roomserver/storage/shared/storage.go | 2 +- 8 files changed, 77 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3621428c3b..4ebe696c64 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,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-20230607161930-ea5ef168992d + github.com/matrix-org/gomatrixserverlib v0.0.0-20230609150234-0a934b0eea2e github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 github.com/mattn/go-sqlite3 v1.14.16 diff --git a/go.sum b/go.sum index 1ee0261f6b..a877d14198 100644 --- a/go.sum +++ b/go.sum @@ -248,6 +248,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -325,6 +326,8 @@ github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530 h1:kHKxCOLcHH8 github.com/matrix-org/gomatrix v0.0.0-20220926102614-ceba4d9f7530/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= github.com/matrix-org/gomatrixserverlib v0.0.0-20230607161930-ea5ef168992d h1:MjL8SXRzhO61aXDFL+gA3Bx1SicqLGL9gCWXDv8jkD8= github.com/matrix-org/gomatrixserverlib v0.0.0-20230607161930-ea5ef168992d/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230609150234-0a934b0eea2e h1:Mz6PVhCpNjT3Ch2rG5OiUTzil8FUjHz3xIJf35TkbsY= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230609150234-0a934b0eea2e/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a h1:awrPDf9LEFySxTLKYBMCiObelNx/cBuv/wzllvCCH3A= github.com/matrix-org/pinecone v0.11.1-0.20230210171230-8c3b24f2649a/go.mod h1:HchJX9oKMXaT2xYFs0Ha/6Zs06mxLU8k6F1ODnrGkeQ= github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 h1:6z4KxomXSIGWqhHcfzExgkH3Z3UkIXry4ibJS4Aqz2Y= diff --git a/roomserver/api/api.go b/roomserver/api/api.go index 8c2cbd6b2c..f009251ba9 100644 --- a/roomserver/api/api.go +++ b/roomserver/api/api.go @@ -2,6 +2,7 @@ package api import ( "context" + "crypto/ed25519" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib/spec" @@ -66,6 +67,9 @@ type RoomserverInternalAPI interface { req *QueryAuthChainRequest, res *QueryAuthChainResponse, ) error + + // GetUserRoomPrivateKey gets the user room key for the specified user. If no key exists yet, a new one is created. + GetUserRoomPrivateKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (ed25519.PrivateKey, error) } type InputRoomEventsAPI interface { diff --git a/roomserver/internal/api.go b/roomserver/internal/api.go index 35b7383a91..bc08942d81 100644 --- a/roomserver/internal/api.go +++ b/roomserver/internal/api.go @@ -2,6 +2,7 @@ package internal import ( "context" + "crypto/ed25519" "github.com/getsentry/sentry-go" "github.com/matrix-org/gomatrixserverlib" @@ -270,3 +271,23 @@ func (r *RoomserverInternalAPI) PerformForget( ) error { return r.Forgetter.PerformForget(ctx, req, resp) } + +// GetUserRoomPrivateKey gets the user room key for the specified user. If no key exists yet, a new one is created. +func (r *RoomserverInternalAPI) GetUserRoomPrivateKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (ed25519.PrivateKey, error) { + key, err := r.DB.SelectUserRoomPrivateKey(ctx, userID, roomID) + if err != nil { + return nil, err + } + // no key found, create one + if len(key) == 0 { + _, key, err = ed25519.GenerateKey(nil) + if err != nil { + return nil, err + } + key, err = r.DB.InsertUserRoomPrivatePublicKey(ctx, userID, roomID, key) + if err != nil { + return nil, err + } + } + return key, nil +} diff --git a/roomserver/internal/perform/perform_create_room.go b/roomserver/internal/perform/perform_create_room.go index a3ba20f70e..7f522cfb03 100644 --- a/roomserver/internal/perform/perform_create_room.go +++ b/roomserver/internal/perform/perform_create_room.go @@ -347,7 +347,30 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo SendAsServer: api.DoNotSendToOtherServers, }) } - if err = api.SendInputRoomEvents(ctx, c.RSAPI, userID.Domain(), inputs, false); err != nil { + + // first send the `m.room.create` event, so we have a roomNID + if err = api.SendInputRoomEvents(ctx, c.RSAPI, userID.Domain(), inputs[:1], false); err != nil { + util.GetLogger(ctx).WithError(err).Error("roomserverAPI.SendInputRoomEvents failed") + return "", &util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + + // create user room key if needed + if createRequest.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs { + _, err = c.RSAPI.GetUserRoomPrivateKey(ctx, userID, roomID) + if err != nil { + util.GetLogger(ctx).WithError(err).Error("GetUserRoomPrivateKey failed") + return "", &util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } + } + } + + // send the remaining events + if err = api.SendInputRoomEvents(ctx, c.RSAPI, userID.Domain(), inputs[1:], false); err != nil { util.GetLogger(ctx).WithError(err).Error("roomserverAPI.SendInputRoomEvents failed") return "", &util.JSONResponse{ Code: http.StatusInternalServerError, diff --git a/roomserver/internal/perform/perform_invite.go b/roomserver/internal/perform/perform_invite.go index 56ee160650..3afc3bbfb0 100644 --- a/roomserver/internal/perform/perform_invite.go +++ b/roomserver/internal/perform/perform_invite.go @@ -183,6 +183,14 @@ func (r *Inviter) PerformInvite( inviteEvent = event } + // if we invited a local user, we can also create a user room key, if it doesn't exist yet. + if isTargetLocal && event.Version() == gomatrixserverlib.RoomVersionPseudoIDs { + _, err = r.RSAPI.GetUserRoomPrivateKey(ctx, *invitedUser, *validRoomID) + if err != nil { + return fmt.Errorf("failed to get user room private key: %w", err) + } + } + // Send the invite event to the roomserver input stream. This will // notify existing users in the room about the invite, update the // membership table and ensure that the event is ready and available diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index d41cc214b5..d71a7f8bcf 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -25,6 +25,7 @@ import ( "github.com/getsentry/sentry-go" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib/spec" + "github.com/matrix-org/util" "github.com/sirupsen/logrus" "github.com/tidwall/gjson" @@ -293,6 +294,20 @@ func (r *Joiner) performJoinRoomByID( switch err.(type) { case nil: + // create user room key if needed + if buildRes.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs { + var roomID *spec.RoomID + roomID, err = spec.NewRoomID(req.RoomIDOrAlias) + if err != nil { + return "", "", rsAPI.ErrInvalidID{Err: fmt.Errorf("room ID %q is invalid: %w", req.RoomIDOrAlias, err)} + } + _, err = r.RSAPI.GetUserRoomPrivateKey(ctx, *userID, *roomID) + if err != nil { + util.GetLogger(ctx).WithError(err).Error("GetUserRoomPrivateKey failed") + return "", "", fmt.Errorf("failed to get user room private key: %w", err) + } + } + // The room join is local. Send the new join event into the // roomserver. First of all check that the user isn't already // a member of the room. This is best-effort (as in we won't diff --git a/roomserver/storage/shared/storage.go b/roomserver/storage/shared/storage.go index cb12b3f571..9809ff4fe0 100644 --- a/roomserver/storage/shared/storage.go +++ b/roomserver/storage/shared/storage.go @@ -1685,7 +1685,7 @@ func (d *Database) SelectUserRoomPrivateKey(ctx context.Context, userID spec.Use return rErr } if roomInfo == nil { - return nil + return eventutil.ErrRoomNoExists{} } key, sErr = d.UserRoomKeyTable.SelectUserRoomPrivateKey(ctx, txn, stateKeyNID, roomInfo.RoomNID) From 0873d83d82cc47001926ca90870e1a6d8e74c1af Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Mon, 12 Jun 2023 13:29:56 +0200 Subject: [PATCH 2/4] Remove duplication --- roomserver/internal/perform/perform_join.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index eb32707206..e7ddeaead0 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -296,11 +296,6 @@ func (r *Joiner) performJoinRoomByID( case nil: // create user room key if needed if buildRes.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs { - var roomID *spec.RoomID - roomID, err = spec.NewRoomID(req.RoomIDOrAlias) - if err != nil { - return "", "", rsAPI.ErrInvalidID{Err: fmt.Errorf("room ID %q is invalid: %w", req.RoomIDOrAlias, err)} - } _, err = r.RSAPI.GetUserRoomPrivateKey(ctx, *userID, *roomID) if err != nil { util.GetLogger(ctx).WithError(err).Error("GetUserRoomPrivateKey failed") From 6a1d689f6535f430a50092785c2b3e5f78ff5acd Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Tue, 13 Jun 2023 13:59:09 +0200 Subject: [PATCH 3/4] Rename method --- roomserver/api/api.go | 4 ++-- roomserver/internal/api.go | 4 ++-- roomserver/internal/perform/perform_create_room.go | 4 ++-- roomserver/internal/perform/perform_invite.go | 2 +- roomserver/internal/perform/perform_join.go | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/roomserver/api/api.go b/roomserver/api/api.go index c5d12f9a4d..fec28841e0 100644 --- a/roomserver/api/api.go +++ b/roomserver/api/api.go @@ -68,8 +68,8 @@ type RoomserverInternalAPI interface { res *QueryAuthChainResponse, ) error - // GetUserRoomPrivateKey gets the user room key for the specified user. If no key exists yet, a new one is created. - GetUserRoomPrivateKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (ed25519.PrivateKey, error) + // GetOrCreateUserRoomPrivateKey gets the user room key for the specified user. If no key exists yet, a new one is created. + GetOrCreateUserRoomPrivateKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (ed25519.PrivateKey, error) } type InputRoomEventsAPI interface { diff --git a/roomserver/internal/api.go b/roomserver/internal/api.go index bc08942d81..4bcd3f3ede 100644 --- a/roomserver/internal/api.go +++ b/roomserver/internal/api.go @@ -272,8 +272,8 @@ func (r *RoomserverInternalAPI) PerformForget( return r.Forgetter.PerformForget(ctx, req, resp) } -// GetUserRoomPrivateKey gets the user room key for the specified user. If no key exists yet, a new one is created. -func (r *RoomserverInternalAPI) GetUserRoomPrivateKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (ed25519.PrivateKey, error) { +// GetOrCreateUserRoomPrivateKey gets the user room key for the specified user. If no key exists yet, a new one is created. +func (r *RoomserverInternalAPI) GetOrCreateUserRoomPrivateKey(ctx context.Context, userID spec.UserID, roomID spec.RoomID) (ed25519.PrivateKey, error) { key, err := r.DB.SelectUserRoomPrivateKey(ctx, userID, roomID) if err != nil { return nil, err diff --git a/roomserver/internal/perform/perform_create_room.go b/roomserver/internal/perform/perform_create_room.go index 75cb9cca26..121b257edc 100644 --- a/roomserver/internal/perform/perform_create_room.go +++ b/roomserver/internal/perform/perform_create_room.go @@ -366,9 +366,9 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo // create user room key if needed if createRequest.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs { - _, err = c.RSAPI.GetUserRoomPrivateKey(ctx, userID, roomID) + _, err = c.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, userID, roomID) if err != nil { - util.GetLogger(ctx).WithError(err).Error("GetUserRoomPrivateKey failed") + util.GetLogger(ctx).WithError(err).Error("GetOrCreateUserRoomPrivateKey failed") return "", &util.JSONResponse{ Code: http.StatusInternalServerError, JSON: spec.InternalServerError{}, diff --git a/roomserver/internal/perform/perform_invite.go b/roomserver/internal/perform/perform_invite.go index 98fbdb879c..cc2c5c191e 100644 --- a/roomserver/internal/perform/perform_invite.go +++ b/roomserver/internal/perform/perform_invite.go @@ -185,7 +185,7 @@ func (r *Inviter) PerformInvite( // if we invited a local user, we can also create a user room key, if it doesn't exist yet. if isTargetLocal && event.Version() == gomatrixserverlib.RoomVersionPseudoIDs { - _, err = r.RSAPI.GetUserRoomPrivateKey(ctx, *invitedUser, *validRoomID) + _, err = r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *invitedUser, *validRoomID) if err != nil { return fmt.Errorf("failed to get user room private key: %w", err) } diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index e7ddeaead0..c0d4b7468b 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -296,9 +296,9 @@ func (r *Joiner) performJoinRoomByID( case nil: // create user room key if needed if buildRes.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs { - _, err = r.RSAPI.GetUserRoomPrivateKey(ctx, *userID, *roomID) + _, err = r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *userID, *roomID) if err != nil { - util.GetLogger(ctx).WithError(err).Error("GetUserRoomPrivateKey failed") + util.GetLogger(ctx).WithError(err).Error("GetOrCreateUserRoomPrivateKey failed") return "", "", fmt.Errorf("failed to get user room private key: %w", err) } } From 13bc2ade23f6ea0c627d27564f0c2da20c742033 Mon Sep 17 00:00:00 2001 From: Till Faelligen <2353100+S7evinK@users.noreply.github.com> Date: Tue, 13 Jun 2023 14:18:42 +0200 Subject: [PATCH 4/4] Use default logrus --- roomserver/internal/perform/perform_join.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index c0d4b7468b..74ed87c744 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -25,7 +25,6 @@ import ( "github.com/getsentry/sentry-go" "github.com/matrix-org/gomatrixserverlib" "github.com/matrix-org/gomatrixserverlib/spec" - "github.com/matrix-org/util" "github.com/sirupsen/logrus" "github.com/tidwall/gjson" @@ -298,7 +297,7 @@ func (r *Joiner) performJoinRoomByID( if buildRes.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs { _, err = r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *userID, *roomID) if err != nil { - util.GetLogger(ctx).WithError(err).Error("GetOrCreateUserRoomPrivateKey failed") + logrus.WithError(err).Error("GetOrCreateUserRoomPrivateKey failed") return "", "", fmt.Errorf("failed to get user room private key: %w", err) } }