Skip to content

Commit

Permalink
bugfix: send [] initially when the poller starts up
Browse files Browse the repository at this point in the history
This ensures we tell clients about used/missing fallback keys initially.
  • Loading branch information
kegsay committed Jan 5, 2024
1 parent 0bd026f commit eae54fb
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 1 deletion.
13 changes: 12 additions & 1 deletion sync2/poller.go
Original file line number Diff line number Diff line change
Expand Up @@ -727,12 +727,23 @@ func (p *poller) parseE2EEData(ctx context.Context, res *SyncResponse) error {
}
shouldSetOTKs = true
}
var changedFallbackTypes []string
var changedFallbackTypes []string // nil slice == don't set, empty slice = no fallback key
shouldSetFallbackKeys := false
if len(p.fallbackKeyTypes) != len(res.DeviceUnusedFallbackKeyTypes) {
// length mismatch always causes an update
changedFallbackTypes = res.DeviceUnusedFallbackKeyTypes
shouldSetFallbackKeys = true
} else {
// lengths match, if they are non-zero then compare each element.
// if they are zero, check for nil vs empty slice.
if len(res.DeviceUnusedFallbackKeyTypes) == 0 {
isCurrentNil := res.DeviceUnusedFallbackKeyTypes == nil
isPreviousNil := p.fallbackKeyTypes == nil
if isCurrentNil != isPreviousNil {
shouldSetFallbackKeys = true
changedFallbackTypes = []string{}
}
}
for i := range res.DeviceUnusedFallbackKeyTypes {
if res.DeviceUnusedFallbackKeyTypes[i] != p.fallbackKeyTypes[i] {
changedFallbackTypes = res.DeviceUnusedFallbackKeyTypes
Expand Down
81 changes: 81 additions & 0 deletions tests-e2e/encryption_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"testing"

"github.com/matrix-org/complement/b"
"github.com/matrix-org/complement/client"
"github.com/matrix-org/sliding-sync/sync3"
"github.com/matrix-org/sliding-sync/sync3/extensions"
Expand Down Expand Up @@ -170,6 +171,86 @@ func TestEncryptionFallbackKey(t *testing.T) {
)
}

// Regression test to make sure EX uploads a fallback key initially.
// EX relies on device_unused_fallback_key_types: [] being present in the
// sync response before it will upload any fallback keys at all, it doesn't
// automatically do it on first login.
func TestEncryptionFallbackKeyToldIfMissingInitially(t *testing.T) {
alice := registerNewUser(t)
bob := registerNewUser(t)
roomID := alice.MustCreateRoom(t, map[string]interface{}{
"preset": "public_chat",
})
bob.JoinRoom(t, roomID, nil)
res := bob.SlidingSync(t, sync3.Request{
Extensions: extensions.Request{
E2EE: &extensions.E2EERequest{
Core: extensions.Core{
Enabled: &boolTrue,
},
},
},
})
m.MatchResponse(t, res, m.MatchFallbackKeyTypes([]string{}))

// upload a fallback key and do another initial request => should include key
keysUploadBody := fmt.Sprintf(`{
"fallback_keys": {
"signed_curve25519:AAAAAAAAADA": {
"fallback": true,
"key": "N8DKj83RTN7lLZrH6shMqHbVhNrxd96OQseQVFmNgTU",
"signatures": {
"%s": {
"ed25519:MUPCQIATEC": "ZnKsVcNmOLBv0LMGeNpCfCO2am9L223EiyddWPx9wPOtuYt6KZIPox/SFwVmqBwkUdnmeTb6tVgCpZwcH8doDw"
}
}
}
}
}`, bob.UserID)
bob.MustDo(t, "POST", []string{"_matrix", "client", "v3", "keys", "upload"},
client.WithRawBody([]byte(keysUploadBody)), client.WithContentType("application/json"),
)
sentinelEventID := bob.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message",
Content: map[string]interface{}{
"msgtype": "m.text",
"body": "Sentinel",
},
})
bob.SlidingSyncUntilEventID(t, "", roomID, sentinelEventID)
res = bob.SlidingSync(t, sync3.Request{
Extensions: extensions.Request{
E2EE: &extensions.E2EERequest{
Core: extensions.Core{
Enabled: &boolTrue,
},
},
},
})
m.MatchResponse(t, res, m.MatchFallbackKeyTypes([]string{"signed_curve25519"}))

// consume the fallback key and do another initial request => should be []
mustClaimOTK(t, alice, bob)
sentinelEventID = bob.SendEventSynced(t, roomID, b.Event{
Type: "m.room.message",
Content: map[string]interface{}{
"msgtype": "m.text",
"body": "Sentinel 2",
},
})
bob.SlidingSyncUntilEventID(t, "", roomID, sentinelEventID)
res = bob.SlidingSync(t, sync3.Request{
Extensions: extensions.Request{
E2EE: &extensions.E2EERequest{
Core: extensions.Core{
Enabled: &boolTrue,
},
},
},
})
m.MatchResponse(t, res, m.MatchFallbackKeyTypes([]string{}))
}

func MatchOTKAndFallbackTypes(otkCount map[string]int, fallbackKeyTypes []string) m.RespMatcher {
return func(r *sync3.Response) error {
err := m.MatchOTKCounts(otkCount)(r)
Expand Down

0 comments on commit eae54fb

Please sign in to comment.