From c7193e24d06a549b2e4a3bfca2d6e0f6c62d5f80 Mon Sep 17 00:00:00 2001 From: Sam Wedgwood <28223854+swedgwood@users.noreply.github.com> Date: Wed, 2 Aug 2023 11:12:14 +0100 Subject: [PATCH] Use `*spec.SenderID` for `QuerySenderIDForUser` (#3164) There are cases where a dendrite instance is unaware of a pseudo ID for a user, the user is not a member of that room. To represent this case, we currently use the 'zero' value, which is often not checked and so causes errors later down the line. To make this case more explict, and to be consistent with `QueryUserIDForSender`, this PR changes this to use a pointer (and `nil` to mean no sender ID). Signed-off-by: `Sam Wedgwood ` --- clientapi/routing/directory.go | 16 +++++++++++----- clientapi/routing/membership.go | 16 ++++++++++------ clientapi/routing/profile.go | 5 ++++- clientapi/routing/redaction.go | 16 +++++++++++++--- clientapi/routing/sendevent.go | 8 +++++--- clientapi/threepid/invites.go | 4 +++- federationapi/federationapi_test.go | 5 +++-- federationapi/internal/perform.go | 4 +++- federationapi/routing/join.go | 7 +++++-- federationapi/routing/leave.go | 8 +++++++- go.mod | 4 ++-- go.sum | 14 ++++++++++---- roomserver/api/api.go | 2 +- roomserver/internal/perform/perform_admin.go | 4 +++- roomserver/internal/perform/perform_invite.go | 6 ++++-- roomserver/internal/perform/perform_join.go | 8 +++++--- roomserver/internal/perform/perform_leave.go | 11 ++++++----- roomserver/internal/perform/perform_upgrade.go | 17 ++++++++++------- roomserver/internal/query/query.go | 17 +++++++++++------ setup/mscs/msc2836/msc2836_test.go | 5 +++-- syncapi/internal/history_visibility.go | 4 ++-- syncapi/storage/shared/storage_consumer.go | 8 ++++---- userapi/consumers/roomserver.go | 5 ++++- 23 files changed, 129 insertions(+), 65 deletions(-) diff --git a/clientapi/routing/directory.go b/clientapi/routing/directory.go index 3ec959b4b..907727662 100644 --- a/clientapi/routing/directory.go +++ b/clientapi/routing/directory.go @@ -204,9 +204,15 @@ func SetLocalAlias( Code: http.StatusInternalServerError, JSON: spec.Unknown("internal server error"), } + } else if senderID == nil { + util.GetLogger(req.Context()).WithField("roomID", *roomID).WithField("userID", *userID).Error("Sender ID not found") + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.Unknown("internal server error"), + } } - aliasAlreadyExists, err := rsAPI.SetRoomAlias(req.Context(), senderID, *roomID, alias) + aliasAlreadyExists, err := rsAPI.SetRoomAlias(req.Context(), *senderID, *roomID, alias) if err != nil { util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.SetRoomAlias failed") return util.JSONResponse{ @@ -293,14 +299,14 @@ func RemoveLocalAlias( } } // TODO: how to handle this case? missing user/room keys seem to be a whole new class of errors - if deviceSenderID == "" { + if deviceSenderID == nil { return util.JSONResponse{ Code: http.StatusInternalServerError, JSON: spec.Unknown("internal server error"), } } - aliasFound, aliasRemoved, err := rsAPI.RemoveRoomAlias(req.Context(), deviceSenderID, alias) + aliasFound, aliasRemoved, err := rsAPI.RemoveRoomAlias(req.Context(), *deviceSenderID, alias) if err != nil { util.GetLogger(req.Context()).WithError(err).Error("aliasAPI.RemoveRoomAlias failed") return util.JSONResponse{ @@ -385,7 +391,7 @@ func SetVisibility( } } senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), *validRoomID, *deviceUserID) - if err != nil { + if err != nil || senderID == nil { return util.JSONResponse{ Code: http.StatusBadRequest, JSON: spec.Unknown("failed to find senderID for this user"), @@ -416,7 +422,7 @@ func SetVisibility( // NOTSPEC: Check if the user's power is greater than power required to change m.room.canonical_alias event power, _ := gomatrixserverlib.NewPowerLevelContentFromEvent(queryEventsRes.StateEvents[0].PDU) - if power.UserLevel(senderID) < power.EventLevel(spec.MRoomCanonicalAlias, true) { + if power.UserLevel(*senderID) < power.EventLevel(spec.MRoomCanonicalAlias, true) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: spec.Forbidden("userID doesn't have power level to change visibility"), diff --git a/clientapi/routing/membership.go b/clientapi/routing/membership.go index def6f0617..8b8cc47bc 100644 --- a/clientapi/routing/membership.go +++ b/clientapi/routing/membership.go @@ -71,7 +71,7 @@ func SendBan( } } senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), *validRoomID, *deviceUserID) - if err != nil { + if err != nil || senderID == nil { return util.JSONResponse{ Code: http.StatusForbidden, JSON: spec.Forbidden("You don't have permission to ban this user, unknown senderID"), @@ -87,7 +87,7 @@ func SendBan( if errRes != nil { return *errRes } - allowedToBan := pl.UserLevel(senderID) >= pl.Ban + allowedToBan := pl.UserLevel(*senderID) >= pl.Ban if !allowedToBan { return util.JSONResponse{ Code: http.StatusForbidden, @@ -169,7 +169,7 @@ func SendKick( } } senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), *validRoomID, *deviceUserID) - if err != nil { + if err != nil || senderID == nil { return util.JSONResponse{ Code: http.StatusForbidden, JSON: spec.Forbidden("You don't have permission to kick this user, unknown senderID"), @@ -185,7 +185,7 @@ func SendKick( if errRes != nil { return *errRes } - allowedToKick := pl.UserLevel(senderID) >= pl.Kick + allowedToKick := pl.UserLevel(*senderID) >= pl.Kick if !allowedToKick { return util.JSONResponse{ Code: http.StatusForbidden, @@ -476,6 +476,8 @@ func buildMembershipEvent( senderID, err := rsAPI.QuerySenderIDForUser(ctx, *validRoomID, *userID) if err != nil { return nil, err + } else if senderID == nil { + return nil, fmt.Errorf("no sender ID for %s in %s", *userID, *validRoomID) } targetID, err := spec.NewUserID(targetUserID, true) @@ -485,6 +487,8 @@ func buildMembershipEvent( targetSenderID, err := rsAPI.QuerySenderIDForUser(ctx, *validRoomID, *targetID) if err != nil { return nil, err + } else if targetSenderID == nil { + return nil, fmt.Errorf("no sender ID for %s in %s", *targetID, *validRoomID) } identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *userID) @@ -492,8 +496,8 @@ func buildMembershipEvent( return nil, err } - return buildMembershipEventDirect(ctx, targetSenderID, reason, profile.DisplayName, profile.AvatarURL, - senderID, device.UserDomain(), membership, roomID, isDirect, identity.KeyID, identity.PrivateKey, evTime, rsAPI) + return buildMembershipEventDirect(ctx, *targetSenderID, reason, profile.DisplayName, profile.AvatarURL, + *senderID, device.UserDomain(), membership, roomID, isDirect, identity.KeyID, identity.PrivateKey, evTime, rsAPI) } // loadProfile lookups the profile of a given user from the database and returns diff --git a/clientapi/routing/profile.go b/clientapi/routing/profile.go index 35da15e0e..66b58507e 100644 --- a/clientapi/routing/profile.go +++ b/clientapi/routing/profile.go @@ -16,6 +16,7 @@ package routing import ( "context" + "fmt" "net/http" "time" @@ -362,8 +363,10 @@ func buildMembershipEvents( senderID, err := rsAPI.QuerySenderIDForUser(ctx, *validRoomID, *fullUserID) if err != nil { return nil, err + } else if senderID == nil { + return nil, fmt.Errorf("sender ID not found for %s in %s", *fullUserID, *validRoomID) } - senderIDString := string(senderID) + senderIDString := string(*senderID) proto := gomatrixserverlib.ProtoEvent{ SenderID: senderIDString, RoomID: roomID, diff --git a/clientapi/routing/redaction.go b/clientapi/routing/redaction.go index 1b9a5a818..230c96d28 100644 --- a/clientapi/routing/redaction.go +++ b/clientapi/routing/redaction.go @@ -74,6 +74,16 @@ func SendRedaction( return *resErr } + // if user is member of room, and sender ID is nil, then this user doesn't have a pseudo ID for some reason, + // which is unexpected. + if senderID == nil { + util.GetLogger(req.Context()).WithField("userID", *deviceUserID).WithField("roomID", roomID).Error("missing sender ID for user, despite having membership") + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.Unknown("internal server error"), + } + } + if txnID != nil { // Try to fetch response from transactionsCache if res, ok := txnCache.FetchTransaction(device.AccessToken, *txnID, req.URL); ok { @@ -98,7 +108,7 @@ func SendRedaction( // "Users may redact their own events, and any user with a power level greater than or equal // to the redact power level of the room may redact events there" // https://matrix.org/docs/spec/client_server/r0.6.1#put-matrix-client-r0-rooms-roomid-redact-eventid-txnid - allowedToRedact := ev.SenderID() == senderID + allowedToRedact := ev.SenderID() == *senderID if !allowedToRedact { plEvent := roomserverAPI.GetStateEvent(req.Context(), rsAPI, roomID, gomatrixserverlib.StateKeyTuple{ EventType: spec.MRoomPowerLevels, @@ -119,7 +129,7 @@ func SendRedaction( ), } } - allowedToRedact = pl.UserLevel(senderID) >= pl.Redact + allowedToRedact = pl.UserLevel(*senderID) >= pl.Redact } if !allowedToRedact { return util.JSONResponse{ @@ -136,7 +146,7 @@ func SendRedaction( // create the new event and set all the fields we can proto := gomatrixserverlib.ProtoEvent{ - SenderID: string(senderID), + SenderID: string(*senderID), RoomID: roomID, Type: spec.MRoomRedaction, Redacts: eventID, diff --git a/clientapi/routing/sendevent.go b/clientapi/routing/sendevent.go index 41a3793ae..172001714 100644 --- a/clientapi/routing/sendevent.go +++ b/clientapi/routing/sendevent.go @@ -251,8 +251,10 @@ func updatePowerLevels(req *http.Request, r map[string]interface{}, roomID strin senderID, err := rsAPI.QuerySenderIDForUser(req.Context(), *validRoomID, *uID) if err != nil { return err + } else if senderID == nil { + return fmt.Errorf("sender ID not found for %s in %s", uID, *validRoomID) } - userMap[string(senderID)] = level + userMap[string(*senderID)] = level delete(userMap, user) } r["users"] = userMap @@ -314,7 +316,7 @@ func generateSendEvent( } } senderID, err := rsAPI.QuerySenderIDForUser(ctx, *validRoomID, *fullUserID) - if err != nil { + if err != nil || senderID == nil { return nil, &util.JSONResponse{ Code: http.StatusNotFound, JSON: spec.NotFound("Unable to find senderID for user"), @@ -323,7 +325,7 @@ func generateSendEvent( // create the new event and set all the fields we can proto := gomatrixserverlib.ProtoEvent{ - SenderID: string(senderID), + SenderID: string(*senderID), RoomID: roomID, Type: eventType, StateKey: stateKey, diff --git a/clientapi/threepid/invites.go b/clientapi/threepid/invites.go index d15cc6d46..365e9f869 100644 --- a/clientapi/threepid/invites.go +++ b/clientapi/threepid/invites.go @@ -366,9 +366,11 @@ func emit3PIDInviteEvent( sender, err := rsAPI.QuerySenderIDForUser(ctx, *validRoomID, *userID) if err != nil { return err + } else if sender == nil { + return fmt.Errorf("sender ID not found for %s in %s", *userID, *validRoomID) } proto := &gomatrixserverlib.ProtoEvent{ - SenderID: string(sender), + SenderID: string(*sender), RoomID: roomID, Type: "m.room.third_party_invite", StateKey: &res.Token, diff --git a/federationapi/federationapi_test.go b/federationapi/federationapi_test.go index 5d167c0ee..c426eb67d 100644 --- a/federationapi/federationapi_test.go +++ b/federationapi/federationapi_test.go @@ -40,8 +40,9 @@ func (f *fedRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID spec return spec.NewUserID(string(senderID), true) } -func (f *fedRoomserverAPI) QuerySenderIDForUser(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (spec.SenderID, error) { - return spec.SenderID(userID.String()), nil +func (f *fedRoomserverAPI) QuerySenderIDForUser(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (*spec.SenderID, error) { + senderID := spec.SenderID(userID.String()) + return &senderID, nil } // PerformJoin will call this function diff --git a/federationapi/internal/perform.go b/federationapi/internal/perform.go index ff00305bf..3bba3ea0d 100644 --- a/federationapi/internal/perform.go +++ b/federationapi/internal/perform.go @@ -481,8 +481,10 @@ func (r *FederationInternalAPI) PerformLeave( senderID, err := r.rsAPI.QuerySenderIDForUser(ctx, *roomID, *userID) if err != nil { return err + } else if senderID == nil { + return fmt.Errorf("sender ID not found for %s in %s", *userID, *roomID) } - senderIDString := string(senderID) + senderIDString := string(*senderID) respMakeLeave.LeaveEvent.Type = spec.MRoomMember respMakeLeave.LeaveEvent.SenderID = senderIDString respMakeLeave.LeaveEvent.StateKey = &senderIDString diff --git a/federationapi/routing/join.go b/federationapi/routing/join.go index a090dbc8d..ce7ad30ff 100644 --- a/federationapi/routing/join.go +++ b/federationapi/routing/join.go @@ -99,7 +99,7 @@ func MakeJoin( Roomserver: rsAPI, } - senderID, err := rsAPI.QuerySenderIDForUser(httpReq.Context(), roomID, userID) + senderIDPtr, err := rsAPI.QuerySenderIDForUser(httpReq.Context(), roomID, userID) if err != nil { util.GetLogger(httpReq.Context()).WithError(err).Error("rsAPI.QuerySenderIDForUser failed") return util.JSONResponse{ @@ -108,8 +108,11 @@ func MakeJoin( } } - if senderID == "" { + var senderID spec.SenderID + if senderIDPtr == nil { senderID = spec.SenderID(userID.String()) + } else { + senderID = *senderIDPtr } input := gomatrixserverlib.HandleMakeJoinInput{ diff --git a/federationapi/routing/leave.go b/federationapi/routing/leave.go index 5c8dd00f3..f28c82115 100644 --- a/federationapi/routing/leave.go +++ b/federationapi/routing/leave.go @@ -94,11 +94,17 @@ func MakeLeave( Code: http.StatusInternalServerError, JSON: spec.InternalServerError{}, } + } else if senderID == nil { + util.GetLogger(httpReq.Context()).WithField("roomID", roomID).WithField("userID", userID).Error("rsAPI.QuerySenderIDForUser returned nil sender ID") + return util.JSONResponse{ + Code: http.StatusInternalServerError, + JSON: spec.InternalServerError{}, + } } input := gomatrixserverlib.HandleMakeLeaveInput{ UserID: userID, - SenderID: senderID, + SenderID: *senderID, RoomID: roomID, RoomVersion: roomVersion, RequestOrigin: request.Origin(), diff --git a/go.mod b/go.mod index 0e77f903e..74b17166c 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-20230721154317-b5b0448aa378 + github.com/matrix-org/gomatrixserverlib v0.0.0-20230802090652-1b697d109d87 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.17 @@ -36,7 +36,7 @@ require ( github.com/prometheus/client_golang v1.16.0 github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.8.2 - github.com/tidwall/gjson v1.14.4 + github.com/tidwall/gjson v1.15.0 github.com/tidwall/sjson v1.2.5 github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/uber/jaeger-lib v2.4.1+incompatible diff --git a/go.sum b/go.sum index 28c60df43..779c28618 100644 --- a/go.sum +++ b/go.sum @@ -113,6 +113,7 @@ github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -175,12 +176,14 @@ github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/huandu/xstrings v1.0.0 h1:pO2K/gKgKaat5LdpAhxhluX2GPQMaI3W5FUz/I/UnWk= github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/errors v1.0.0 h1:yiq7kjCLll1BiaRuNY53MGI0+EQ3rF6GB+wvboZDefM= github.com/juju/errors v1.0.0/go.mod h1:B5x9thDqx0wIMH3+aLIMP9HjItInYWObRovoCFM5Qe8= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kardianos/minwinsvc v1.0.2 h1:JmZKFJQrmTGa/WiW+vkJXKmfzdjabuEW4Tirj5lLdR0= github.com/kardianos/minwinsvc v1.0.2/go.mod h1:LUZNYhNmxujx2tR7FbdxqYJ9XDDoCd3MQcl1o//FWl4= @@ -207,8 +210,10 @@ 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-20230721154317-b5b0448aa378 h1:a6sfiJiNZWVbPRHvEB/YlpqSg+Dh7El+824mzccSk68= -github.com/matrix-org/gomatrixserverlib v0.0.0-20230721154317-b5b0448aa378/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230801102756-b66c2627dc08 h1:uy1mlUraKrEbUzZ3KrSQp/nLxMccVhIJM8mZSIbQzeA= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230801102756-b66c2627dc08/go.mod h1:H9V9N3Uqn1bBJqYJNGK1noqtgJTaCEhtTdcH/mp50uU= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230802090652-1b697d109d87 h1:z0RFUknidOShRxkvjT3ovGCWnusyplu6OLjFHcbDYaE= +github.com/matrix-org/gomatrixserverlib v0.0.0-20230802090652-1b697d109d87/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= @@ -241,6 +246,7 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/jwt/v2 v2.4.1 h1:Y35W1dgbbz2SQUYDPCaclXcuqleVmpbRa7646Jf2EX4= github.com/nats-io/jwt/v2 v2.4.1/go.mod h1:24BeQtRwxRV8ruvC4CojXlx/WQ/VjuwlYiH+vu/+ibI= github.com/nats-io/nats-server/v2 v2.9.19 h1:OF9jSKZGo425C/FcVVIvNgpd36CUe7aVTTXEZRJk6kA= @@ -322,8 +328,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= -github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.15.0 h1:5n/pM+v3r5ujuNl4YLZLsQ+UE5jlkLVm7jMzT5Mpolw= +github.com/tidwall/gjson v1.15.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= diff --git a/roomserver/api/api.go b/roomserver/api/api.go index ed87ce93a..69997fc41 100644 --- a/roomserver/api/api.go +++ b/roomserver/api/api.go @@ -97,7 +97,7 @@ type InputRoomEventsAPI interface { } type QuerySenderIDAPI interface { - QuerySenderIDForUser(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (spec.SenderID, error) + QuerySenderIDForUser(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (*spec.SenderID, error) QueryUserIDForSender(ctx context.Context, roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) } diff --git a/roomserver/internal/perform/perform_admin.go b/roomserver/internal/perform/perform_admin.go index dd7132624..2888067b4 100644 --- a/roomserver/internal/perform/perform_admin.go +++ b/roomserver/internal/perform/perform_admin.go @@ -292,10 +292,12 @@ func (r *Admin) PerformAdminDownloadState( senderID, err := r.Queryer.QuerySenderIDForUser(ctx, *validRoomID, *fullUserID) if err != nil { return err + } else if senderID == nil { + return fmt.Errorf("sender ID not found for %s in %s", *fullUserID, *validRoomID) } proto := &gomatrixserverlib.ProtoEvent{ Type: "org.matrix.dendrite.state_download", - SenderID: string(senderID), + SenderID: string(*senderID), RoomID: roomID, Content: spec.RawJSON("{}"), } diff --git a/roomserver/internal/perform/perform_invite.go b/roomserver/internal/perform/perform_invite.go index 278ddd7d8..e07780d68 100644 --- a/roomserver/internal/perform/perform_invite.go +++ b/roomserver/internal/perform/perform_invite.go @@ -133,6 +133,8 @@ func (r *Inviter) PerformInvite( senderID, err := r.RSAPI.QuerySenderIDForUser(ctx, req.InviteInput.RoomID, req.InviteInput.Inviter) if err != nil { return err + } else if senderID == nil { + return fmt.Errorf("sender ID not found for %s in %s", req.InviteInput.Inviter, req.InviteInput.RoomID) } info, err := r.DB.RoomInfo(ctx, req.InviteInput.RoomID.String()) if err != nil { @@ -140,7 +142,7 @@ func (r *Inviter) PerformInvite( } proto := gomatrixserverlib.ProtoEvent{ - SenderID: string(senderID), + SenderID: string(*senderID), RoomID: req.InviteInput.RoomID.String(), Type: "m.room.member", } @@ -187,7 +189,7 @@ func (r *Inviter) PerformInvite( UserIDQuerier: func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) { return r.RSAPI.QueryUserIDForSender(ctx, roomID, senderID) }, - SenderIDQuerier: func(roomID spec.RoomID, userID spec.UserID) (spec.SenderID, error) { + SenderIDQuerier: func(roomID spec.RoomID, userID spec.UserID) (*spec.SenderID, error) { return r.RSAPI.QuerySenderIDForUser(ctx, roomID, userID) }, SenderIDCreator: func(ctx context.Context, userID spec.UserID, roomID spec.RoomID, roomVersion string) (spec.SenderID, ed25519.PrivateKey, error) { diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index dfce9cc77..23988e467 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -201,11 +201,11 @@ func (r *Joiner) performJoinRoomByID( if err == nil && info != nil { switch info.RoomVersion { case gomatrixserverlib.RoomVersionPseudoIDs: - senderID, err = r.Queryer.QuerySenderIDForUser(ctx, *roomID, *userID) - if err == nil { + senderIDPtr, queryErr := r.Queryer.QuerySenderIDForUser(ctx, *roomID, *userID) + if queryErr == nil { checkInvitePending = true } - if senderID == "" { + if senderIDPtr == nil { // create user room key if needed key, keyErr := r.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, *userID, *roomID) if keyErr != nil { @@ -213,6 +213,8 @@ func (r *Joiner) performJoinRoomByID( return "", "", fmt.Errorf("GetOrCreateUserRoomPrivateKey failed: %w", keyErr) } senderID = spec.SenderIDFromPseudoIDKey(key) + } else { + senderID = *senderIDPtr } default: checkInvitePending = true diff --git a/roomserver/internal/perform/perform_leave.go b/roomserver/internal/perform/perform_leave.go index a20896cf7..5c63a6684 100644 --- a/roomserver/internal/perform/perform_leave.go +++ b/roomserver/internal/perform/perform_leave.go @@ -73,6 +73,7 @@ func (r *Leaver) PerformLeave( return nil, fmt.Errorf("room ID %q is invalid", req.RoomID) } +// nolint:gocyclo func (r *Leaver) performLeaveRoomByID( ctx context.Context, req *api.PerformLeaveRequest, @@ -83,20 +84,20 @@ func (r *Leaver) performLeaveRoomByID( return nil, err } leaver, err := r.RSAPI.QuerySenderIDForUser(ctx, *roomID, req.Leaver) - if err != nil { + if err != nil || leaver == nil { return nil, fmt.Errorf("leaver %s has no matching senderID in this room", req.Leaver.String()) } // If there's an invite outstanding for the room then respond to // that. - isInvitePending, senderUser, eventID, _, err := helpers.IsInvitePending(ctx, r.DB, req.RoomID, leaver) + isInvitePending, senderUser, eventID, _, err := helpers.IsInvitePending(ctx, r.DB, req.RoomID, *leaver) if err == nil && isInvitePending { sender, serr := r.RSAPI.QueryUserIDForSender(ctx, *roomID, senderUser) if serr != nil || sender == nil { return nil, fmt.Errorf("sender %q has no matching userID", senderUser) } if !r.Cfg.Matrix.IsLocalServerName(sender.Domain()) { - return r.performFederatedRejectInvite(ctx, req, res, *sender, eventID, leaver) + return r.performFederatedRejectInvite(ctx, req, res, *sender, eventID, *leaver) } // check that this is not a "server notice room" accData := &userapi.QueryAccountDataResponse{} @@ -132,7 +133,7 @@ func (r *Leaver) performLeaveRoomByID( StateToFetch: []gomatrixserverlib.StateKeyTuple{ { EventType: spec.MRoomMember, - StateKey: string(leaver), + StateKey: string(*leaver), }, }, } @@ -157,7 +158,7 @@ func (r *Leaver) performLeaveRoomByID( } // Prepare the template for the leave event. - senderIDString := string(leaver) + senderIDString := string(*leaver) proto := gomatrixserverlib.ProtoEvent{ Type: spec.MRoomMember, SenderID: senderIDString, diff --git a/roomserver/internal/perform/perform_upgrade.go b/roomserver/internal/perform/perform_upgrade.go index 74c62cd9e..c32e10d53 100644 --- a/roomserver/internal/perform/perform_upgrade.go +++ b/roomserver/internal/perform/perform_upgrade.go @@ -62,10 +62,13 @@ func (r *Upgrader) performRoomUpgrade( if err != nil { util.GetLogger(ctx).WithError(err).Error("Failed getting senderID for user") return "", err + } else if senderID == nil { + util.GetLogger(ctx).WithField("userID", userID).WithField("roomID", *fullRoomID).Error("No senderID for user") + return "", fmt.Errorf("No sender ID for %s in %s", userID, *fullRoomID) } // 1. Check if the user is authorized to actually perform the upgrade (can send m.room.tombstone) - if !r.userIsAuthorized(ctx, senderID, roomID) { + if !r.userIsAuthorized(ctx, *senderID, roomID) { return "", api.ErrNotAllowed{Err: fmt.Errorf("You don't have permission to upgrade the room, power level too low.")} } @@ -83,20 +86,20 @@ func (r *Upgrader) performRoomUpgrade( } // Make the tombstone event - tombstoneEvent, pErr := r.makeTombstoneEvent(ctx, evTime, senderID, userID.Domain(), roomID, newRoomID) + tombstoneEvent, pErr := r.makeTombstoneEvent(ctx, evTime, *senderID, userID.Domain(), roomID, newRoomID) if pErr != nil { return "", pErr } // Generate the initial events we need to send into the new room. This includes copied state events and bans // as well as the power level events needed to set up the room - eventsToMake, pErr := r.generateInitialEvents(ctx, oldRoomRes, senderID, roomID, roomVersion, tombstoneEvent) + eventsToMake, pErr := r.generateInitialEvents(ctx, oldRoomRes, *senderID, roomID, roomVersion, tombstoneEvent) if pErr != nil { return "", pErr } // Send the setup events to the new room - if pErr = r.sendInitialEvents(ctx, evTime, senderID, userID.Domain(), newRoomID, roomVersion, eventsToMake); pErr != nil { + if pErr = r.sendInitialEvents(ctx, evTime, *senderID, userID.Domain(), newRoomID, roomVersion, eventsToMake); pErr != nil { return "", pErr } @@ -111,17 +114,17 @@ func (r *Upgrader) performRoomUpgrade( } // If the old room had a canonical alias event, it should be deleted in the old room - if pErr = r.clearOldCanonicalAliasEvent(ctx, oldRoomRes, evTime, senderID, userID.Domain(), roomID); pErr != nil { + if pErr = r.clearOldCanonicalAliasEvent(ctx, oldRoomRes, evTime, *senderID, userID.Domain(), roomID); pErr != nil { return "", pErr } // 4. Move local aliases to the new room - if pErr = moveLocalAliases(ctx, roomID, newRoomID, senderID, r.URSAPI); pErr != nil { + if pErr = moveLocalAliases(ctx, roomID, newRoomID, *senderID, r.URSAPI); pErr != nil { return "", pErr } // 6. Restrict power levels in the old room - if pErr = r.restrictOldRoomPowerLevels(ctx, evTime, senderID, userID.Domain(), roomID); pErr != nil { + if pErr = r.restrictOldRoomPowerLevels(ctx, evTime, *senderID, userID.Domain(), roomID); pErr != nil { return "", pErr } diff --git a/roomserver/internal/query/query.go b/roomserver/internal/query/query.go index 11e5564dc..0fe0f4f27 100644 --- a/roomserver/internal/query/query.go +++ b/roomserver/internal/query/query.go @@ -283,7 +283,7 @@ func (r *Queryer) QueryMembershipForUser( return err } - return r.QueryMembershipForSenderID(ctx, *roomID, senderID, response) + return r.QueryMembershipForSenderID(ctx, *roomID, *senderID, response) } // QueryMembershipAtEvent returns the known memberships at a given event. @@ -1009,21 +1009,26 @@ func (r *Queryer) QueryRestrictedJoinAllowed(ctx context.Context, roomID spec.Ro return verImpl.CheckRestrictedJoin(ctx, r.Cfg.Global.ServerName, &api.JoinRoomQuerier{Roomserver: r}, roomID, senderID) } -func (r *Queryer) QuerySenderIDForUser(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (spec.SenderID, error) { +func (r *Queryer) QuerySenderIDForUser(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (*spec.SenderID, error) { version, err := r.DB.GetRoomVersion(ctx, roomID.String()) if err != nil { - return "", err + return nil, err } switch version { case gomatrixserverlib.RoomVersionPseudoIDs: key, err := r.DB.SelectUserRoomPublicKey(ctx, userID, roomID) if err != nil { - return "", err + return nil, err + } else if key == nil { + return nil, nil + } else { + senderID := spec.SenderID(spec.Base64Bytes(key).Encode()) + return &senderID, nil } - return spec.SenderID(spec.Base64Bytes(key).Encode()), nil default: - return spec.SenderID(userID.String()), nil + senderID := spec.SenderID(userID.String()) + return &senderID, nil } } diff --git a/setup/mscs/msc2836/msc2836_test.go b/setup/mscs/msc2836/msc2836_test.go index 16fb3efe1..ecbab706f 100644 --- a/setup/mscs/msc2836/msc2836_test.go +++ b/setup/mscs/msc2836/msc2836_test.go @@ -529,8 +529,9 @@ func (r *testRoomserverAPI) QueryUserIDForSender(ctx context.Context, roomID spe return spec.NewUserID(string(senderID), true) } -func (r *testRoomserverAPI) QuerySenderIDForUser(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (spec.SenderID, error) { - return spec.SenderID(userID.String()), nil +func (r *testRoomserverAPI) QuerySenderIDForUser(ctx context.Context, roomID spec.RoomID, userID spec.UserID) (*spec.SenderID, error) { + senderID := spec.SenderID(userID.String()) + return &senderID, nil } func (r *testRoomserverAPI) QueryEventsByID(ctx context.Context, req *roomserver.QueryEventsByIDRequest, res *roomserver.QueryEventsByIDResponse) error { diff --git a/syncapi/internal/history_visibility.go b/syncapi/internal/history_visibility.go index ce6846ca4..3c2308954 100644 --- a/syncapi/internal/history_visibility.go +++ b/syncapi/internal/history_visibility.go @@ -144,8 +144,8 @@ func ApplyHistoryVisibilityFilter( return nil, err } senderID, err := rsAPI.QuerySenderIDForUser(ctx, *roomID, *user) - if err == nil { - if ev.Type() == spec.MRoomMember && ev.StateKeyEquals(string(senderID)) { + if err == nil && senderID != nil { + if ev.Type() == spec.MRoomMember && ev.StateKeyEquals(string(*senderID)) { eventsFiltered = append(eventsFiltered, ev) continue } diff --git a/syncapi/storage/shared/storage_consumer.go b/syncapi/storage/shared/storage_consumer.go index 746a324fa..69e64cc79 100644 --- a/syncapi/storage/shared/storage_consumer.go +++ b/syncapi/storage/shared/storage_consumer.go @@ -122,13 +122,13 @@ func (d *Database) StreamEventsToEvents(ctx context.Context, device *userapi.Dev continue } deviceSenderID, err := rsAPI.QuerySenderIDForUser(ctx, *roomID, *userID) - if err != nil { + if err != nil || deviceSenderID == nil { logrus.WithFields(logrus.Fields{ "event_id": out[i].EventID(), }).WithError(err).Warnf("Failed to add transaction ID to event") continue } - if deviceSenderID == in[i].SenderID() && device.SessionID == in[i].TransactionID.SessionID { + if *deviceSenderID == in[i].SenderID() && device.SessionID == in[i].TransactionID.SessionID { err := out[i].SetUnsignedField( "transaction_id", in[i].TransactionID.TransactionID, ) @@ -527,11 +527,11 @@ func getMembershipFromEvent(ctx context.Context, ev gomatrixserverlib.PDU, userI return "", "" } senderID, err := rsAPI.QuerySenderIDForUser(ctx, *roomID, *fullUser) - if err != nil { + if err != nil || senderID == nil { return "", "" } - if ev.Type() != "m.room.member" || !ev.StateKeyEquals(string(senderID)) { + if ev.Type() != "m.room.member" || !ev.StateKeyEquals(string(*senderID)) { return "", "" } membership, err := ev.Membership() diff --git a/userapi/consumers/roomserver.go b/userapi/consumers/roomserver.go index 1f866ef4d..a88b2129d 100644 --- a/userapi/consumers/roomserver.go +++ b/userapi/consumers/roomserver.go @@ -840,8 +840,11 @@ func (s *OutputRoomEventConsumer) notifyHTTP(ctx context.Context, event *rstypes if err != nil { logger.WithError(err).Errorf("Failed to get local user senderID for room %s: %s", userID.String(), event.RoomID()) return nil, err + } else if localSender == nil { + logger.WithError(err).Errorf("Failed to get local user senderID for room %s: %s", userID.String(), event.RoomID()) + return nil, fmt.Errorf("no sender ID for user %s in %s", userID.String(), roomID.String()) } - if event.StateKey() != nil && *event.StateKey() == string(localSender) { + if event.StateKey() != nil && *event.StateKey() == string(*localSender) { req.Notification.UserIsTarget = true } }