mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 09:40:43 +00:00
fix(matrix): defer secret storage during forced repair
This commit is contained in:
@@ -277,6 +277,49 @@ describe("MatrixCryptoBootstrapper", () => {
|
||||
expectSecretStorageRepairRetry(deps, crypto, bootstrapCrossSigning);
|
||||
});
|
||||
|
||||
it("does not mutate secret storage before forced repair fails on password UIA without a password", async () => {
|
||||
const deps = createBootstrapperDeps();
|
||||
deps.getPassword = vi.fn(() => undefined);
|
||||
const bootstrapCrossSigning = vi.fn<
|
||||
({
|
||||
authUploadDeviceSigningKeys,
|
||||
}: {
|
||||
authUploadDeviceSigningKeys?: <T>(
|
||||
makeRequest: (authData: Record<string, unknown> | null) => Promise<T>,
|
||||
) => Promise<T>;
|
||||
}) => Promise<void>
|
||||
>(async ({ authUploadDeviceSigningKeys }) => {
|
||||
await authUploadDeviceSigningKeys?.(async (authData) => {
|
||||
if (authData === null) {
|
||||
throw new Error("need auth");
|
||||
}
|
||||
if (authData.type === "m.login.dummy") {
|
||||
throw new Error("dummy rejected");
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
});
|
||||
const crypto = createCryptoApi({
|
||||
bootstrapCrossSigning,
|
||||
getDeviceVerificationStatus: vi.fn(async () => createVerifiedDeviceStatus()),
|
||||
});
|
||||
const bootstrapper = new MatrixCryptoBootstrapper(
|
||||
deps as unknown as MatrixCryptoBootstrapperDeps<MatrixRawEvent>,
|
||||
);
|
||||
|
||||
await expect(
|
||||
bootstrapper.bootstrap(crypto, {
|
||||
strict: true,
|
||||
forceResetCrossSigning: true,
|
||||
allowSecretStorageRecreateWithoutRecoveryKey: true,
|
||||
}),
|
||||
).rejects.toThrow(
|
||||
"Matrix cross-signing key upload requires UIA; provide matrix.password for m.login.password fallback",
|
||||
);
|
||||
|
||||
expect(deps.recoveryKeyStore.bootstrapSecretStorageWithRecoveryKey).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("fails in strict mode when cross-signing keys are still unpublished", async () => {
|
||||
const deps = createBootstrapperDeps();
|
||||
const crypto = createCryptoApi({
|
||||
|
||||
@@ -47,14 +47,18 @@ export class MatrixCryptoBootstrapper<TRawEvent extends MatrixRawEvent> {
|
||||
options: MatrixCryptoBootstrapOptions = {},
|
||||
): Promise<MatrixCryptoBootstrapResult> {
|
||||
const strict = options.strict === true;
|
||||
const deferSecretStorageBootstrapUntilAfterCrossSigning =
|
||||
options.forceResetCrossSigning === true;
|
||||
// Register verification listeners before expensive bootstrap work so incoming requests
|
||||
// are not missed during startup.
|
||||
this.registerVerificationRequestHandler(crypto);
|
||||
await this.bootstrapSecretStorage(crypto, {
|
||||
strict,
|
||||
allowSecretStorageRecreateWithoutRecoveryKey:
|
||||
options.allowSecretStorageRecreateWithoutRecoveryKey === true,
|
||||
});
|
||||
if (!deferSecretStorageBootstrapUntilAfterCrossSigning) {
|
||||
await this.bootstrapSecretStorage(crypto, {
|
||||
strict,
|
||||
allowSecretStorageRecreateWithoutRecoveryKey:
|
||||
options.allowSecretStorageRecreateWithoutRecoveryKey === true,
|
||||
});
|
||||
}
|
||||
const crossSigning = await this.bootstrapCrossSigning(crypto, {
|
||||
forceResetCrossSigning: options.forceResetCrossSigning === true,
|
||||
allowAutomaticCrossSigningReset: options.allowAutomaticCrossSigningReset !== false,
|
||||
@@ -62,6 +66,9 @@ export class MatrixCryptoBootstrapper<TRawEvent extends MatrixRawEvent> {
|
||||
options.allowSecretStorageRecreateWithoutRecoveryKey === true,
|
||||
strict,
|
||||
});
|
||||
// Forced repair may need password UIA to upload new cross-signing keys. Delay any
|
||||
// secret-storage repair/recreation until after that step succeeds so passwordless bots do
|
||||
// not partially mutate SSSS on homeservers that require password-based UIA.
|
||||
await this.bootstrapSecretStorage(crypto, {
|
||||
strict,
|
||||
allowSecretStorageRecreateWithoutRecoveryKey:
|
||||
|
||||
Reference in New Issue
Block a user