diff --git a/federationapi/internal/perform.go b/federationapi/internal/perform.go index 5a98cd218..61e1a949b 100644 --- a/federationapi/internal/perform.go +++ b/federationapi/internal/perform.go @@ -2,6 +2,7 @@ package internal import ( "context" + "crypto/ed25519" "encoding/json" "errors" "fmt" @@ -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) { + SenderIDCreator: 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.SenderIDFromPseudoIDKey(key), 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) diff --git a/federationapi/routing/join.go b/federationapi/routing/join.go index b886382f7..f0784e604 100644 --- a/federationapi/routing/join.go +++ b/federationapi/routing/join.go @@ -15,6 +15,7 @@ package routing import ( + "context" "fmt" "net/http" "sort" @@ -113,6 +114,10 @@ func MakeJoin( } } + if senderID == "" { + senderID = spec.SenderID(userID.String()) + } + input := gomatrixserverlib.HandleMakeJoinInput{ Context: httpReq.Context(), UserID: userID, @@ -224,6 +229,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) { diff --git a/roomserver/api/api.go b/roomserver/api/api.go index 5d7728bd4..ab56529c5 100644 --- a/roomserver/api/api.go +++ b/roomserver/api/api.go @@ -74,6 +74,7 @@ type RoomserverInternalAPI interface { type UserRoomPrivateKeyCreator interface { // 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) + StoreUserRoomPublicKey(ctx context.Context, senderID spec.SenderID, userID spec.UserID, roomID spec.RoomID) error } type InputRoomEventsAPI interface { @@ -235,7 +236,7 @@ type FederationRoomserverAPI interface { QueryBulkStateContentAPI QuerySenderIDAPI UserRoomPrivateKeyCreator - + AssignRoomNID(ctx context.Context, roomID spec.RoomID, roomVersion gomatrixserverlib.RoomVersion) (roomNID types.RoomNID, err error) 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 diff --git a/roomserver/internal/api.go b/roomserver/internal/api.go index 22ae23c80..2e12671ff 100644 --- a/roomserver/internal/api.go +++ b/roomserver/internal/api.go @@ -289,6 +289,15 @@ func (r *RoomserverInternalAPI) GetOrCreateUserRoomPrivateKey(ctx context.Contex return key, nil } +func (r *RoomserverInternalAPI) StoreUserRoomPublicKey(ctx context.Context, senderID spec.SenderID, userID spec.UserID, roomID spec.RoomID) error { + pubKeyBytes, err := senderID.RawBytes() + if err != nil { + return err + } + _, err = r.DB.InsertUserRoomPublicKey(ctx, userID, roomID, ed25519.PublicKey(pubKeyBytes)) + return err +} + 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 { @@ -307,7 +316,7 @@ func (r *RoomserverInternalAPI) SigningIdentityFor(ctx context.Context, roomID s } return fclient.SigningIdentity{ PrivateKey: privKey, - KeyID: "ed25519", + KeyID: "ed25519:1", ServerName: "self", }, nil } @@ -317,3 +326,7 @@ func (r *RoomserverInternalAPI) SigningIdentityFor(ctx context.Context, roomID s } return *identity, err } + +func (r *RoomserverInternalAPI) AssignRoomNID(ctx context.Context, roomID spec.RoomID, roomVersion gomatrixserverlib.RoomVersion) (roomNID types.RoomNID, err error) { + return r.DB.AssignRoomNID(ctx, roomID, roomVersion) +} diff --git a/roomserver/internal/perform/perform_create_room.go b/roomserver/internal/perform/perform_create_room.go index 9316c1290..8c9656453 100644 --- a/roomserver/internal/perform/perform_create_room.go +++ b/roomserver/internal/perform/perform_create_room.go @@ -196,7 +196,7 @@ func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roo // sign all events with the pseudo ID key identity = &fclient.SigningIdentity{ ServerName: "self", - KeyID: "ed25519", + KeyID: "ed25519:1", PrivateKey: pseudoIDKey, } } diff --git a/roomserver/internal/perform/perform_join.go b/roomserver/internal/perform/perform_join.go index 3883a5b96..c14554640 100644 --- a/roomserver/internal/perform/perform_join.go +++ b/roomserver/internal/perform/perform_join.go @@ -314,7 +314,7 @@ func (r *Joiner) performJoinRoomByID( // sign the event with the pseudo ID key identity = fclient.SigningIdentity{ ServerName: "self", - KeyID: "ed25519", + KeyID: "ed25519:1", PrivateKey: pseudoIDKey, } }