mas: added "admin's replacement without uia" endpoint

i.e. /_synapse/admin/v1/users/{userID}/_allow_cross_signing_replacement_without_uia
This commit is contained in:
Roman Isaev 2024-12-30 02:11:30 +00:00
parent 63a199cec3
commit 9d9841d02e
No known key found for this signature in database
GPG key ID: 7BE2B6A6C89AEC7F
10 changed files with 168 additions and 29 deletions

View file

@ -680,6 +680,11 @@ type ClientKeyAPI interface {
QueryKeys(ctx context.Context, req *QueryKeysRequest, res *QueryKeysResponse)
QueryMasterKeys(ctx context.Context, req *QueryMasterKeysRequest, res *QueryMasterKeysResponse)
PerformUploadKeys(ctx context.Context, req *PerformUploadKeysRequest, res *PerformUploadKeysResponse) error
PerformAllowingMasterCrossSigningKeyReplacementWithoutUIA(
ctx context.Context,
req *PerformAllowingMasterCrossSigningKeyReplacementWithoutUIARequest,
res *PerformAllowingMasterCrossSigningKeyReplacementWithoutUIAResponse,
) error
PerformUploadDeviceSignatures(ctx context.Context, req *PerformUploadDeviceSignaturesRequest, res *PerformUploadDeviceSignaturesResponse)
// PerformClaimKeys claims one-time keys for use in pre-key messages
@ -908,6 +913,15 @@ type PerformUploadDeviceKeysResponse struct {
Error *KeyError
}
type PerformAllowingMasterCrossSigningKeyReplacementWithoutUIARequest struct {
UserID string
Duration time.Duration
}
type PerformAllowingMasterCrossSigningKeyReplacementWithoutUIAResponse struct {
Timestamp int64
}
type PerformUploadDeviceSignaturesRequest struct {
Signatures map[string]map[gomatrixserverlib.KeyID]fclient.CrossSigningForKeyOrDevice
// The user that uploaded the sig, should be populated by the clientapi.

View file

@ -96,6 +96,16 @@ func sanityCheckKey(key fclient.CrossSigningKey, userID string, purpose fclient.
return nil
}
func (a *UserInternalAPI) PerformAllowingMasterCrossSigningKeyReplacementWithoutUIA(
ctx context.Context,
req *api.PerformAllowingMasterCrossSigningKeyReplacementWithoutUIARequest,
res *api.PerformAllowingMasterCrossSigningKeyReplacementWithoutUIAResponse,
) error {
var err error
res.Timestamp, err = a.KeyDatabase.UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx, req.UserID, req.Duration)
return err
}
// nolint:gocyclo
func (a *UserInternalAPI) PerformUploadDeviceKeys(ctx context.Context, req *api.PerformUploadDeviceKeysRequest, res *api.PerformUploadDeviceKeysResponse) {
// Find the keys to store.

View file

@ -10,6 +10,7 @@ import (
"context"
"encoding/json"
"errors"
"time"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/gomatrixserverlib/fclient"
@ -231,6 +232,7 @@ type KeyDatabase interface {
StoreCrossSigningKeysForUser(ctx context.Context, userID string, keyMap types.CrossSigningKeyMap, updatableWithoutUIABeforeMs *int64) error
StoreCrossSigningSigsForTarget(ctx context.Context, originUserID string, originKeyID gomatrixserverlib.KeyID, targetUserID string, targetKeyID gomatrixserverlib.KeyID, signature spec.Base64Bytes) error
UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx context.Context, userID string, duration time.Duration) (int64, error)
DeleteStaleDeviceLists(
ctx context.Context,

View file

@ -10,6 +10,7 @@ import (
"context"
"database/sql"
"fmt"
"time"
"github.com/element-hq/dendrite/internal"
"github.com/element-hq/dendrite/internal/sqlutil"
@ -42,11 +43,17 @@ const upsertCrossSigningKeysForUserSQL = "" +
" VALUES($1, $2, $3)" +
" ON CONFLICT (user_id, key_type) DO UPDATE SET key_data = $3"
const updateMasterCrossSigningKeyAllowReplacementWithoutUiaSQL = "" +
"UPDATE keyserver_cross_signing_keys" +
" SET updatable_without_uia_before_ms = $3" +
" WHERE user_id = $1 AND key_type = $2"
type crossSigningKeysStatements struct {
db *sql.DB
selectCrossSigningKeysForUserStmt *sql.Stmt
selectCrossSigningKeysForUserAndKeyTypeStmt *sql.Stmt
upsertCrossSigningKeysForUserStmt *sql.Stmt
db *sql.DB
selectCrossSigningKeysForUserStmt *sql.Stmt
selectCrossSigningKeysForUserAndKeyTypeStmt *sql.Stmt
upsertCrossSigningKeysForUserStmt *sql.Stmt
updateMasterCrossSigningKeyAllowReplacementWithoutUiaStmt *sql.Stmt
}
func NewPostgresCrossSigningKeysTable(db *sql.DB) (tables.CrossSigningKeys, error) {
@ -61,6 +68,7 @@ func NewPostgresCrossSigningKeysTable(db *sql.DB) (tables.CrossSigningKeys, erro
{&s.selectCrossSigningKeysForUserStmt, selectCrossSigningKeysForUserSQL},
{&s.selectCrossSigningKeysForUserAndKeyTypeStmt, selectCrossSigningKeysForUserAndKeyTypeSQL},
{&s.upsertCrossSigningKeysForUserStmt, upsertCrossSigningKeysForUserSQL},
{&s.updateMasterCrossSigningKeyAllowReplacementWithoutUiaStmt, updateMasterCrossSigningKeyAllowReplacementWithoutUiaSQL},
}.Prepare(db)
}
@ -138,3 +146,16 @@ func (s *crossSigningKeysStatements) UpsertCrossSigningKeysForUser(
}
return nil
}
func (s *crossSigningKeysStatements) UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx context.Context, txn *sql.Tx, userID string, duration time.Duration) (int64, error) {
keyTypeInt, _ := types.KeyTypePurposeToInt[fclient.CrossSigningKeyPurposeMaster]
ts := time.Now().Add(duration).UnixMilli()
result, err := sqlutil.TxStmt(txn, s.updateMasterCrossSigningKeyAllowReplacementWithoutUiaStmt).ExecContext(ctx, userID, keyTypeInt, ts)
if err != nil {
return -1, err
}
if n, _ := result.RowsAffected(); n == 0 {
return -1, sql.ErrNoRows
}
return ts, nil
}

View file

@ -1159,7 +1159,19 @@ func (d *KeyDatabase) StoreCrossSigningKeysForUser(ctx context.Context, userID s
})
}
// StoreCrossSigningSigsForTarget stores a signature for a target user ID and key/dvice.
// UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA updates the 'updatable_without_uia_before_ms' attribute of the master cross-signing key.
// Normally this attribute depending on its value marks the master key as replaceable without UIA.
func (d *KeyDatabase) UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx context.Context, userID string, duration time.Duration) (int64, error) {
var ts int64
err := d.Writer.Do(d.DB, nil, func(txn *sql.Tx) error {
var err error
ts, err = d.CrossSigningKeysTable.UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx, txn, userID, duration)
return err
})
return ts, err
}
// StoreCrossSigningSigsForTarget stores a signature for a target user ID and key/device.
func (d *KeyDatabase) StoreCrossSigningSigsForTarget(
ctx context.Context,
originUserID string, originKeyID gomatrixserverlib.KeyID,

View file

@ -10,6 +10,7 @@ import (
"context"
"database/sql"
"fmt"
"time"
"github.com/element-hq/dendrite/internal"
"github.com/element-hq/dendrite/internal/sqlutil"
@ -41,11 +42,17 @@ const upsertCrossSigningKeysForUserSQL = "" +
"INSERT OR REPLACE INTO keyserver_cross_signing_keys (user_id, key_type, key_data, updatable_without_uia_before_ms)" +
" VALUES($1, $2, $3, $4)"
const updateMasterCrossSigningKeyAllowReplacementWithoutUiaSQL = "" +
"UPDATE keyserver_cross_signing_keys" +
" SET updatable_without_uia_before_ms = $3" +
" WHERE user_id = $1 AND key_type = $2"
type crossSigningKeysStatements struct {
db *sql.DB
selectCrossSigningKeysForUserStmt *sql.Stmt
selectCrossSigningKeysForUserAndKeyTypeStmt *sql.Stmt
upsertCrossSigningKeysForUserStmt *sql.Stmt
db *sql.DB
selectCrossSigningKeysForUserStmt *sql.Stmt
selectCrossSigningKeysForUserAndKeyTypeStmt *sql.Stmt
upsertCrossSigningKeysForUserStmt *sql.Stmt
updateMasterCrossSigningKeyAllowReplacementWithoutUiaStmt *sql.Stmt
}
func NewSqliteCrossSigningKeysTable(db *sql.DB) (tables.CrossSigningKeys, error) {
@ -60,6 +67,7 @@ func NewSqliteCrossSigningKeysTable(db *sql.DB) (tables.CrossSigningKeys, error)
{&s.selectCrossSigningKeysForUserStmt, selectCrossSigningKeysForUserSQL},
{&s.selectCrossSigningKeysForUserAndKeyTypeStmt, selectCrossSigningKeysForUserAndKeyTypeSQL},
{&s.upsertCrossSigningKeysForUserStmt, upsertCrossSigningKeysForUserSQL},
{&s.updateMasterCrossSigningKeyAllowReplacementWithoutUiaStmt, updateMasterCrossSigningKeyAllowReplacementWithoutUiaSQL},
}.Prepare(db)
}
@ -137,3 +145,16 @@ func (s *crossSigningKeysStatements) UpsertCrossSigningKeysForUser(
}
return nil
}
func (s *crossSigningKeysStatements) UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx context.Context, txn *sql.Tx, userID string, duration time.Duration) (int64, error) {
keyTypeInt, _ := types.KeyTypePurposeToInt[fclient.CrossSigningKeyPurposeMaster]
ts := time.Now().Add(duration).UnixMilli()
result, err := sqlutil.TxStmt(txn, s.updateMasterCrossSigningKeyAllowReplacementWithoutUiaStmt).ExecContext(ctx, userID, keyTypeInt, ts)
if err != nil {
return -1, err
}
if n, _ := result.RowsAffected(); n == 0 {
return -1, sql.ErrNoRows
}
return ts, nil
}

View file

@ -200,6 +200,7 @@ type CrossSigningKeys interface {
SelectCrossSigningKeysForUser(ctx context.Context, txn *sql.Tx, userID string) (r types.CrossSigningKeyMap, err error)
SelectCrossSigningKeysForUserAndKeyType(ctx context.Context, txn *sql.Tx, userID string, keyType fclient.CrossSigningKeyPurpose) (r types.CrossSigningKeyMap, err error)
UpsertCrossSigningKeysForUser(ctx context.Context, txn *sql.Tx, userID string, keyType fclient.CrossSigningKeyPurpose, keyData spec.Base64Bytes, updatableWithoutUIABeforeMs *int64) error
UpdateMasterCrossSigningKeyAllowReplacementWithoutUIA(ctx context.Context, txn *sql.Tx, userID string, duration time.Duration) (int64, error)
}
type CrossSigningSigs interface {