mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-29 01:33:10 -06:00
Process master/self-signing keys from devices call
This commit is contained in:
parent
a1309b3afc
commit
c990e79387
|
|
@ -113,6 +113,41 @@ func (a *KeyInternalAPI) PerformUploadDeviceKeys(ctx context.Context, req *api.P
|
||||||
masterKey, hasMasterKey = existingKeys[gomatrixserverlib.CrossSigningKeyPurposeMaster]
|
masterKey, hasMasterKey = existingKeys[gomatrixserverlib.CrossSigningKeyPurposeMaster]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the user isn't a local user and we haven't successfully found a key
|
||||||
|
// through any local means then ask over federation.
|
||||||
|
if !hasMasterKey {
|
||||||
|
_, host, err := gomatrixserverlib.SplitID('@', req.UserID)
|
||||||
|
if err != nil {
|
||||||
|
res.Error = &api.KeyError{
|
||||||
|
Err: "Retrieving cross-signing keys from federation failed: " + err.Error(),
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
keys, err := a.FedClient.QueryKeys(ctx, host, map[string][]string{
|
||||||
|
req.UserID: {},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
res.Error = &api.KeyError{
|
||||||
|
Err: "Retrieving cross-signing keys from federation failed: " + err.Error(),
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch k := keys.MasterKeys[req.UserID].CrossSigningBody.(type) {
|
||||||
|
case *gomatrixserverlib.CrossSigningKey:
|
||||||
|
if err := sanityCheckKey(*k, req.UserID, gomatrixserverlib.CrossSigningKeyPurposeMaster); err != nil {
|
||||||
|
res.Error = &api.KeyError{
|
||||||
|
Err: "User-signing key sanity check failed: " + err.Error(),
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
res.Error = &api.KeyError{
|
||||||
|
Err: "Unexpected type for master key retrieved from federation",
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If we still don't have a master key at this point then there's nothing else
|
// If we still don't have a master key at this point then there's nothing else
|
||||||
// we can do - we've checked both the request and the database.
|
// we can do - we've checked both the request and the database.
|
||||||
if !hasMasterKey {
|
if !hasMasterKey {
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ type DeviceListUpdater struct {
|
||||||
mu *sync.Mutex // protects UserIDToMutex
|
mu *sync.Mutex // protects UserIDToMutex
|
||||||
|
|
||||||
db DeviceListUpdaterDatabase
|
db DeviceListUpdaterDatabase
|
||||||
|
api DeviceListUpdaterAPI
|
||||||
producer KeyChangeProducer
|
producer KeyChangeProducer
|
||||||
fedClient fedsenderapi.FederationClient
|
fedClient fedsenderapi.FederationClient
|
||||||
workerChans []chan gomatrixserverlib.ServerName
|
workerChans []chan gomatrixserverlib.ServerName
|
||||||
|
|
@ -114,6 +115,10 @@ type DeviceListUpdaterDatabase interface {
|
||||||
DeviceKeysJSON(ctx context.Context, keys []api.DeviceMessage) error
|
DeviceKeysJSON(ctx context.Context, keys []api.DeviceMessage) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeviceListUpdaterAPI interface {
|
||||||
|
PerformUploadDeviceKeys(ctx context.Context, req *api.PerformUploadDeviceKeysRequest, res *api.PerformUploadDeviceKeysResponse)
|
||||||
|
}
|
||||||
|
|
||||||
// KeyChangeProducer is the interface for producers.KeyChange useful for testing.
|
// KeyChangeProducer is the interface for producers.KeyChange useful for testing.
|
||||||
type KeyChangeProducer interface {
|
type KeyChangeProducer interface {
|
||||||
ProduceKeyChanges(keys []api.DeviceMessage) error
|
ProduceKeyChanges(keys []api.DeviceMessage) error
|
||||||
|
|
@ -121,13 +126,14 @@ type KeyChangeProducer interface {
|
||||||
|
|
||||||
// NewDeviceListUpdater creates a new updater which fetches fresh device lists when they go stale.
|
// NewDeviceListUpdater creates a new updater which fetches fresh device lists when they go stale.
|
||||||
func NewDeviceListUpdater(
|
func NewDeviceListUpdater(
|
||||||
db DeviceListUpdaterDatabase, producer KeyChangeProducer, fedClient fedsenderapi.FederationClient,
|
db DeviceListUpdaterDatabase, api DeviceListUpdaterAPI, producer KeyChangeProducer,
|
||||||
numWorkers int,
|
fedClient fedsenderapi.FederationClient, numWorkers int,
|
||||||
) *DeviceListUpdater {
|
) *DeviceListUpdater {
|
||||||
return &DeviceListUpdater{
|
return &DeviceListUpdater{
|
||||||
userIDToMutex: make(map[string]*sync.Mutex),
|
userIDToMutex: make(map[string]*sync.Mutex),
|
||||||
mu: &sync.Mutex{},
|
mu: &sync.Mutex{},
|
||||||
db: db,
|
db: db,
|
||||||
|
api: api,
|
||||||
producer: producer,
|
producer: producer,
|
||||||
fedClient: fedClient,
|
fedClient: fedClient,
|
||||||
workerChans: make([]chan gomatrixserverlib.ServerName, numWorkers),
|
workerChans: make([]chan gomatrixserverlib.ServerName, numWorkers),
|
||||||
|
|
@ -367,6 +373,23 @@ func (u *DeviceListUpdater) processServer(serverName gomatrixserverlib.ServerNam
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if res.MasterKey != nil || res.SelfSigningKey != nil {
|
||||||
|
uploadReq := &api.PerformUploadDeviceKeysRequest{
|
||||||
|
UserID: userID,
|
||||||
|
}
|
||||||
|
uploadRes := &api.PerformUploadDeviceKeysResponse{}
|
||||||
|
if res.MasterKey != nil {
|
||||||
|
if err = sanityCheckKey(*res.MasterKey, userID, gomatrixserverlib.CrossSigningKeyPurposeMaster); err == nil {
|
||||||
|
uploadReq.MasterKey = *res.MasterKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if res.SelfSigningKey != nil {
|
||||||
|
if err = sanityCheckKey(*res.MasterKey, userID, gomatrixserverlib.CrossSigningKeyPurposeSelfSigning); err == nil {
|
||||||
|
uploadReq.SelfSigningKey = *res.SelfSigningKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
u.api.PerformUploadDeviceKeys(ctx, uploadReq, uploadRes)
|
||||||
|
}
|
||||||
err = u.updateDeviceList(&res)
|
err = u.updateDeviceList(&res)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.WithError(err).WithField("user_id", userID).Error("fetched device list but failed to store/emit it")
|
logger.WithError(err).WithField("user_id", userID).Error("fetched device list but failed to store/emit it")
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,13 @@ func (d *mockDeviceListUpdaterDatabase) DeviceKeysJSON(ctx context.Context, keys
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mockDeviceListUpdaterAPI struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *mockDeviceListUpdaterAPI) PerformUploadDeviceKeys(ctx context.Context, req *api.PerformUploadDeviceKeysRequest, res *api.PerformUploadDeviceKeysResponse) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
type roundTripper struct {
|
type roundTripper struct {
|
||||||
fn func(*http.Request) (*http.Response, error)
|
fn func(*http.Request) (*http.Response, error)
|
||||||
}
|
}
|
||||||
|
|
@ -122,8 +129,9 @@ func TestUpdateHavePrevID(t *testing.T) {
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
ap := &mockDeviceListUpdaterAPI{}
|
||||||
producer := &mockKeyChangeProducer{}
|
producer := &mockKeyChangeProducer{}
|
||||||
updater := NewDeviceListUpdater(db, producer, nil, 1)
|
updater := NewDeviceListUpdater(db, ap, producer, nil, 1)
|
||||||
event := gomatrixserverlib.DeviceListUpdateEvent{
|
event := gomatrixserverlib.DeviceListUpdateEvent{
|
||||||
DeviceDisplayName: "Foo Bar",
|
DeviceDisplayName: "Foo Bar",
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
|
|
@ -166,6 +174,7 @@ func TestUpdateNoPrevID(t *testing.T) {
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
ap := &mockDeviceListUpdaterAPI{}
|
||||||
producer := &mockKeyChangeProducer{}
|
producer := &mockKeyChangeProducer{}
|
||||||
remoteUserID := "@alice:example.somewhere"
|
remoteUserID := "@alice:example.somewhere"
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
@ -193,7 +202,7 @@ func TestUpdateNoPrevID(t *testing.T) {
|
||||||
`)),
|
`)),
|
||||||
}, nil
|
}, nil
|
||||||
})
|
})
|
||||||
updater := NewDeviceListUpdater(db, producer, fedClient, 2)
|
updater := NewDeviceListUpdater(db, ap, producer, fedClient, 2)
|
||||||
if err := updater.Start(); err != nil {
|
if err := updater.Start(); err != nil {
|
||||||
t.Fatalf("failed to start updater: %s", err)
|
t.Fatalf("failed to start updater: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,20 +51,19 @@ func NewInternalAPI(
|
||||||
Producer: producer,
|
Producer: producer,
|
||||||
DB: db,
|
DB: db,
|
||||||
}
|
}
|
||||||
updater := internal.NewDeviceListUpdater(db, keyChangeProducer, fedClient, 8) // 8 workers TODO: configurable
|
|
||||||
go func() {
|
|
||||||
if err := updater.Start(); err != nil {
|
|
||||||
logrus.WithError(err).Panicf("failed to start device list updater")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
ap := &internal.KeyInternalAPI{
|
ap := &internal.KeyInternalAPI{
|
||||||
DB: db,
|
DB: db,
|
||||||
ThisServer: cfg.Matrix.ServerName,
|
ThisServer: cfg.Matrix.ServerName,
|
||||||
FedClient: fedClient,
|
FedClient: fedClient,
|
||||||
Producer: keyChangeProducer,
|
Producer: keyChangeProducer,
|
||||||
Updater: updater,
|
|
||||||
}
|
}
|
||||||
|
updater := internal.NewDeviceListUpdater(db, ap, keyChangeProducer, fedClient, 8) // 8 workers TODO: configurable
|
||||||
|
ap.Updater = updater
|
||||||
|
go func() {
|
||||||
|
if err := updater.Start(); err != nil {
|
||||||
|
logrus.WithError(err).Panicf("failed to start device list updater")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
keyconsumer := consumers.NewOutputSigningKeyUpdateConsumer(
|
keyconsumer := consumers.NewOutputSigningKeyUpdateConsumer(
|
||||||
base.ProcessContext, base.Cfg, consumer, db, ap,
|
base.ProcessContext, base.Cfg, consumer, db, ap,
|
||||||
|
|
|
||||||
|
|
@ -550,3 +550,6 @@ Will not back up to an old backup version
|
||||||
Can create more than 10 backup versions
|
Can create more than 10 backup versions
|
||||||
Can delete backup
|
Can delete backup
|
||||||
Deleted & recreated backups are empty
|
Deleted & recreated backups are empty
|
||||||
|
Can upload self-signing keys
|
||||||
|
Fails to upload self-signing keys with no auth
|
||||||
|
Fails to upload self-signing key without master key
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue