From 6728ac523cec8318ca030b64ed0df4dc2cdbebea Mon Sep 17 00:00:00 2001 From: Max Sandholm Date: Thu, 22 Jun 2023 09:09:19 +0300 Subject: [PATCH] Add option to delete outdated inbound keys (keys which lack the metadata about when they're safe to delete) --- bridge/bridgeconfig/config.go | 1 + bridge/crypto.go | 10 ++++++++++ crypto/sql_store.go | 16 ++++++++++++++++ crypto/store.go | 6 ++++++ 4 files changed, 33 insertions(+) diff --git a/bridge/bridgeconfig/config.go b/bridge/bridgeconfig/config.go index c80f5555..4cb9c777 100644 --- a/bridge/bridgeconfig/config.go +++ b/bridge/bridgeconfig/config.go @@ -184,6 +184,7 @@ type EncryptionConfig struct { DeletePrevOnNewSession bool `yaml:"delete_prev_on_new_session"` DeleteOnDeviceDelete bool `yaml:"delete_on_device_delete"` PeriodicallyDeleteExpired bool `yaml:"periodically_delete_expired"` + DeleteOutdatedInbound bool `yaml:"delete_outdated_inbound"` } `yaml:"delete_keys"` VerificationLevels struct { diff --git a/bridge/crypto.go b/bridge/crypto.go index c9a97894..3c3c27c0 100644 --- a/bridge/crypto.go +++ b/bridge/crypto.go @@ -110,6 +110,16 @@ func (helper *CryptoHelper) Init() error { go helper.mach.ExpiredKeyDeleteLoop(ctx) } + if encryptionConfig.DeleteKeys.DeleteOutdatedInbound { + deleted, err := helper.store.RedactOutdatedGroupSessions() + if err != nil { + return err + } + if len(deleted) > 0 { + helper.log.Debug().Int("deleted", len(deleted)).Msg("Deleted inbound keys which lacked expiration metadata") + } + } + helper.client.Syncer = &cryptoSyncer{helper.mach} helper.client.Store = helper.store diff --git a/crypto/sql_store.go b/crypto/sql_store.go index 09175727..a46fb286 100644 --- a/crypto/sql_store.go +++ b/crypto/sql_store.go @@ -418,6 +418,22 @@ func (store *SQLCryptoStore) RedactExpiredGroupSessions() ([]id.SessionID, error return sessionIDs, err } +func (store *SQLCryptoStore) RedactOutdatedGroupSessions() ([]id.SessionID, error) { + res, err := store.DB.Query(` + UPDATE crypto_megolm_inbound_session + SET withheld_code=$1, withheld_reason=$2, session=NULL, forwarding_chains=NULL + WHERE account_id=$3 AND session IS NOT NULL AND received_at IS NULL + RETURNING session_id + `, event.RoomKeyWithheldBeeperRedacted, "Session redacted: outdated", store.AccountID) + var sessionIDs []id.SessionID + for res.Next() { + var sessionID id.SessionID + _ = res.Scan(&sessionID) + sessionIDs = append(sessionIDs, sessionID) + } + return sessionIDs, err +} + func (store *SQLCryptoStore) PutWithheldGroupSession(content event.RoomKeyWithheldEventContent) error { _, err := store.DB.Exec("INSERT INTO crypto_megolm_inbound_session (session_id, sender_key, room_id, withheld_code, withheld_reason, received_at, account_id) VALUES ($1, $2, $3, $4, $5, $6, $7)", content.SessionID, content.SenderKey, content.RoomID, content.Code, content.Reason, time.Now().UTC(), store.AccountID) diff --git a/crypto/store.go b/crypto/store.go index 55f70491..99e464d2 100644 --- a/crypto/store.go +++ b/crypto/store.go @@ -59,6 +59,8 @@ type Store interface { RedactGroupSessions(id.RoomID, id.SenderKey, string) ([]id.SessionID, error) // RedactExpiredGroupSessions removes the session data for all inbound Megolm sessions that have expired. RedactExpiredGroupSessions() ([]id.SessionID, error) + // RedactOutdatedGroupSessions removes the session data for all inbound Megolm sessions that are lacking the expiration metadata. + RedactOutdatedGroupSessions() ([]id.SessionID, error) // PutWithheldGroupSession tells the store that a specific Megolm session was withheld. PutWithheldGroupSession(event.RoomKeyWithheldEventContent) error // GetWithheldGroupSession gets the event content that was previously inserted with PutWithheldGroupSession. @@ -317,6 +319,10 @@ func (gs *MemoryStore) RedactExpiredGroupSessions() ([]id.SessionID, error) { return nil, fmt.Errorf("not implemented") } +func (gs *MemoryStore) RedactOutdatedGroupSessions() ([]id.SessionID, error) { + return nil, fmt.Errorf("not implemented") +} + func (gs *MemoryStore) getWithheldGroupSessions(roomID id.RoomID, senderKey id.SenderKey) map[id.SessionID]*event.RoomKeyWithheldEventContent { room, ok := gs.WithheldGroupSessions[roomID] if !ok {