Get signing identity depending on the room version

This commit is contained in:
Till Faelligen 2023-06-14 16:52:48 +02:00
parent 50615c7609
commit 34ab4d11ed
No known key found for this signature in database
GPG key ID: ACCDC9606D472758
15 changed files with 143 additions and 48 deletions

View file

@ -419,11 +419,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
@ -441,6 +436,17 @@ func buildMembershipEvent(
if err != nil {
return nil, err
}
validRoomID, err := spec.NewRoomID(roomID)
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)
}

View file

@ -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
}
@ -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
}
@ -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{
@ -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:
@ -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{}
@ -391,12 +390,22 @@ func buildMembershipEvents(
return nil, err
}
identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain())
validRoomID, err := spec.NewRoomID(roomID)
if err != nil {
return nil, err
}
event, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, evTime, rsAPI, nil)
user, err := spec.NewUserID(userID, true)
if err != nil {
return nil, err
}
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
}

View file

@ -143,7 +143,15 @@ func SendRedaction(
}
}
identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain())
validRoomID, err := spec.NewRoomID(roomID)
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{},
}
}
identity, err := rsAPI.SigningIdentityFor(req.Context(), *validRoomID, *deviceUserID)
if err != nil {
return util.JSONResponse{
Code: http.StatusInternalServerError,
@ -152,7 +160,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,

View file

@ -129,7 +129,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
}
@ -261,7 +261,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) {
@ -297,7 +296,15 @@ func generateSendEvent(
}
}
identity, err := cfg.Matrix.SigningIdentityFor(device.UserDomain())
validRoomID, err := spec.NewRoomID(roomID)
if err != nil {
return nil, &util.JSONResponse{
Code: http.StatusInternalServerError,
JSON: spec.InternalServerError{},
}
}
identity, err := rsAPI.SigningIdentityFor(ctx, *validRoomID, *fullUserID)
if err != nil {
return nil, &util.JSONResponse{
Code: http.StatusInternalServerError,
@ -306,7 +313,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:

View file

@ -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
@ -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
}

View file

@ -64,7 +64,13 @@ func MakeJoin(
}
createJoinTemplate := func(proto *gomatrixserverlib.ProtoEvent) (gomatrixserverlib.PDU, []gomatrixserverlib.PDU, error) {
identity, signErr := cfg.Matrix.SigningIdentityFor(request.Destination())
// TODO: remove this once the join dance understands pseudo IDs
var dummyUserID *spec.UserID
dummyUserID, err = spec.NewUserID(fmt.Sprintf("@dummy:%s", request.Destination()), true)
if err != nil {
return nil, nil, err
}
identity, signErr := rsAPI.SigningIdentityFor(httpReq.Context(), roomID, *dummyUserID)
if signErr != nil {
util.GetLogger(httpReq.Context()).WithError(signErr).Errorf("obtaining signing identity for %s failed", request.Destination())
return nil, nil, spec.NotFound(fmt.Sprintf("Server name %q does not exist", request.Destination()))
@ -73,7 +79,7 @@ func MakeJoin(
queryRes := api.QueryLatestEventsAndStateResponse{
RoomVersion: roomVersion,
}
event, signErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, identity, time.Now(), rsAPI, &queryRes)
event, signErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, &identity, time.Now(), rsAPI, &queryRes)
switch e := signErr.(type) {
case nil:
case eventutil.ErrRoomNoExists:

View file

@ -59,14 +59,20 @@ func MakeLeave(
}
createLeaveTemplate := func(proto *gomatrixserverlib.ProtoEvent) (gomatrixserverlib.PDU, []gomatrixserverlib.PDU, error) {
identity, signErr := cfg.Matrix.SigningIdentityFor(request.Destination())
// TODO: remove this once the leave dance understands pseudo IDs
var dummyUserID *spec.UserID
dummyUserID, err = spec.NewUserID(fmt.Sprintf("@dummy:%s", request.Destination()), true)
if err != nil {
return nil, nil, err
}
identity, signErr := rsAPI.SigningIdentityFor(httpReq.Context(), roomID, *dummyUserID)
if signErr != nil {
util.GetLogger(httpReq.Context()).WithError(signErr).Errorf("obtaining signing identity for %s failed", request.Destination())
return nil, nil, spec.NotFound(fmt.Sprintf("Server name %q does not exist", request.Destination()))
}
queryRes := api.QueryLatestEventsAndStateResponse{}
event, buildErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, identity, time.Now(), rsAPI, &queryRes)
event, buildErr := eventutil.QueryAndBuildEvent(httpReq.Context(), proto, &identity, time.Now(), rsAPI, &queryRes)
switch e := buildErr.(type) {
case nil:
case eventutil.ErrRoomNoExists:

View file

@ -5,6 +5,7 @@ import (
"crypto/ed25519"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
@ -210,6 +211,7 @@ type ClientRoomserverAPI interface {
PerformForget(ctx context.Context, req *PerformForgetRequest, resp *PerformForgetResponse) error
SetRoomAlias(ctx context.Context, req *SetRoomAliasRequest, res *SetRoomAliasResponse) error
RemoveRoomAlias(ctx context.Context, req *RemoveRoomAliasRequest, res *RemoveRoomAliasResponse) error
SigningIdentityFor(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error)
}
type UserRoomserverAPI interface {
@ -228,7 +230,7 @@ type FederationRoomserverAPI interface {
QueryLatestEventsAndStateAPI
QueryBulkStateContentAPI
QuerySenderIDAPI
SigningIdentityFor(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error)
// QueryServerBannedFromRoom returns whether a server is banned from a room by server ACLs.
QueryServerBannedFromRoom(ctx context.Context, req *QueryServerBannedFromRoomRequest, res *QueryServerBannedFromRoomResponse) error
QueryMembershipForUser(ctx context.Context, req *QueryMembershipForUserRequest, res *QueryMembershipForUserResponse) error

View file

@ -114,6 +114,7 @@ func (r *RoomserverInternalAPI) GetAliasesForRoomID(
}
// RemoveRoomAlias implements alias.RoomserverInternalAPI
// nolint: gocyclo
func (r *RoomserverInternalAPI) RemoveRoomAlias(
ctx context.Context,
request *api.RemoveRoomAliasRequest,
@ -182,9 +183,11 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias(
return err
}
senderDomain := sender.Domain()
identity, err := r.Cfg.Global.SigningIdentityFor(senderDomain)
validRoomID, err := spec.NewRoomID(roomID)
if err != nil {
return err
}
identity, err := r.SigningIdentityFor(ctx, *validRoomID, *sender)
if err != nil {
return err
}
@ -210,7 +213,7 @@ func (r *RoomserverInternalAPI) RemoveRoomAlias(
return err
}
newEvent, err := eventutil.BuildEvent(ctx, proto, identity, time.Now(), &eventsNeeded, stateRes)
newEvent, err := eventutil.BuildEvent(ctx, proto, &identity, time.Now(), &eventsNeeded, stateRes)
if err != nil {
return err
}

View file

@ -6,6 +6,7 @@ import (
"github.com/getsentry/sentry-go"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/fclient"
"github.com/matrix-org/gomatrixserverlib/spec"
"github.com/matrix-org/util"
"github.com/nats-io/nats.go"
@ -110,11 +111,6 @@ func (r *RoomserverInternalAPI) SetFederationAPI(fsAPI fsAPI.RoomserverFederatio
r.fsAPI = fsAPI
r.KeyRing = keyRing
identity, err := r.Cfg.Global.SigningIdentityFor(r.ServerName)
if err != nil {
logrus.Panic(err)
}
r.Inputer = &input.Inputer{
Cfg: &r.Cfg.RoomServer,
ProcessContext: r.ProcessContext,
@ -125,7 +121,7 @@ func (r *RoomserverInternalAPI) SetFederationAPI(fsAPI fsAPI.RoomserverFederatio
NATSClient: r.NATSClient,
Durable: nats.Durable(r.Durable),
ServerName: r.ServerName,
SigningIdentity: identity,
SigningIdentity: r.SigningIdentityFor,
FSAPI: fsAPI,
KeyRing: keyRing,
ACLs: r.ServerACLs,
@ -291,3 +287,34 @@ func (r *RoomserverInternalAPI) GetOrCreateUserRoomPrivateKey(ctx context.Contex
}
return key, nil
}
func (r *RoomserverInternalAPI) SigningIdentityFor(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error) {
roomVersion, ok := r.Cache.GetRoomVersion(roomID.String())
if !ok {
roomInfo, err := r.DB.RoomInfo(ctx, roomID.String())
if err != nil {
return fclient.SigningIdentity{}, err
}
if roomInfo != nil {
roomVersion = roomInfo.RoomVersion
}
}
if roomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
privKey, err := r.GetOrCreateUserRoomPrivateKey(ctx, senderID, roomID)
if err != nil {
return fclient.SigningIdentity{}, err
}
logrus.Infof("XXX: using user signing key")
return fclient.SigningIdentity{
PrivateKey: privKey,
KeyID: "ed25519",
ServerName: "self",
}, nil
}
logrus.Infof("XXX: using config signing key")
identity, err := r.Cfg.Global.SigningIdentityFor(senderID.Domain())
if err != nil {
return fclient.SigningIdentity{}, err
}
return *identity, err
}

View file

@ -81,7 +81,7 @@ type Inputer struct {
JetStream nats.JetStreamContext
Durable nats.SubOpt
ServerName spec.ServerName
SigningIdentity *fclient.SigningIdentity
SigningIdentity func(ctx context.Context, roomID spec.RoomID, senderID spec.UserID) (fclient.SigningIdentity, error)
FSAPI fedapi.RoomserverFederationAPI
KeyRing gomatrixserverlib.JSONVerifier
ACLs *acls.ServerACLs

View file

@ -886,7 +886,22 @@ func (r *Inputer) kickGuests(ctx context.Context, event gomatrixserverlib.PDU, r
return err
}
event, err := eventutil.BuildEvent(ctx, fledglingEvent, r.SigningIdentity, time.Now(), &eventsNeeded, latestRes)
validRoomID, err := spec.NewRoomID(event.RoomID())
if err != nil {
return err
}
userID, err := spec.NewUserID(stateKey, true)
if err != nil {
return err
}
signingIdentity, err := r.SigningIdentity(ctx, *validRoomID, *userID)
if err != nil {
return err
}
event, err := eventutil.BuildEvent(ctx, fledglingEvent, &signingIdentity, time.Now(), &eventsNeeded, latestRes)
if err != nil {
return err
}

View file

@ -150,7 +150,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
}
// get the signing identity
identity, err := c.Cfg.Matrix.SigningIdentityFor(userID.Domain())
identity, err := c.Cfg.Matrix.SigningIdentityFor(userID.Domain()) // we MUST use the server signing mxid_mapping
if err != nil {
logrus.WithError(err).WithField("domain", userID.Domain()).Error("unable to find signing identity for domain")
return "", &util.JSONResponse{
@ -187,8 +187,8 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
// sign all events with the pseudo ID key
identity = &fclient.SigningIdentity{
ServerName: userID.Domain(),
KeyID: "self",
ServerName: "self",
KeyID: "ed25519",
PrivateKey: pseudoIDKey,
}
}
@ -404,6 +404,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo
inputs := make([]api.InputRoomEvent, 0, len(builtEvents))
for _, event := range builtEvents {
logrus.Infof("XXX: built event: %s", string(event.JSON()))
inputs = append(inputs, api.InputRoomEvent{
Kind: api.KindNew,
Event: event,

View file

@ -285,7 +285,7 @@ func (r *Joiner) performJoinRoomByID(
// but everyone has since left. I suspect it does the wrong thing.
var buildRes rsAPI.QueryLatestEventsAndStateResponse
identity, err := r.Cfg.Matrix.SigningIdentityFor(userDomain)
identity, err := r.RSAPI.SigningIdentityFor(ctx, *roomID, *userID)
if err != nil {
return "", "", fmt.Errorf("error joining local room: %q", err)
}
@ -311,9 +311,9 @@ func (r *Joiner) performJoinRoomByID(
req.Content["mxid_mapping"] = mapping
// sign the event with the pseudo ID key
identity = &fclient.SigningIdentity{
ServerName: userID.Domain(),
KeyID: "self",
identity = fclient.SigningIdentity{
ServerName: "self",
KeyID: "ed25519",
PrivateKey: pseudoIDKey,
}
}
@ -322,7 +322,7 @@ func (r *Joiner) performJoinRoomByID(
return "", "", fmt.Errorf("eb.SetContent: %w", err)
}
event, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, time.Now(), r.RSAPI, &buildRes)
event, err := eventutil.QueryAndBuildEvent(ctx, &proto, &identity, time.Now(), r.RSAPI, &buildRes)
switch err.(type) {
case nil:

View file

@ -173,12 +173,17 @@ func (r *Leaver) performLeaveRoomByID(
// TODO: Check what happens if the room exists on the server
// but everyone has since left. I suspect it does the wrong thing.
validRoomID, err := spec.NewRoomID(req.RoomID)
if err != nil {
return nil, err
}
var buildRes rsAPI.QueryLatestEventsAndStateResponse
identity, err := r.Cfg.Matrix.SigningIdentityFor(req.Leaver.Domain())
identity, err := r.RSAPI.SigningIdentityFor(ctx, *validRoomID, req.Leaver)
if err != nil {
return nil, fmt.Errorf("SigningIdentityFor: %w", err)
}
event, err := eventutil.QueryAndBuildEvent(ctx, &proto, identity, time.Now(), r.RSAPI, &buildRes)
event, err := eventutil.QueryAndBuildEvent(ctx, &proto, &identity, time.Now(), r.RSAPI, &buildRes)
if err != nil {
return nil, fmt.Errorf("eventutil.QueryAndBuildEvent: %w", err)
}