Merge pull request #1584 from famedly/td/fixAwaitSecrets
fix: validate account_data values instead of checking them in syncUpdates
This commit is contained in:
		
						commit
						067a61ed18
					
				|  | @ -248,15 +248,16 @@ class SSSS { | ||||||
|     }() |     }() | ||||||
|         .firstWhere((keyId) => getKey(keyId) == null); |         .firstWhere((keyId) => getKey(keyId) == null); | ||||||
| 
 | 
 | ||||||
|     final accountDataType = EventTypes.secretStorageKey(keyId); |     final accountDataTypeKeyId = EventTypes.secretStorageKey(keyId); | ||||||
|     // noooow we set the account data |     // noooow we set the account data | ||||||
|     final waitForAccountData = client.onSync.stream.firstWhere((syncUpdate) => | 
 | ||||||
|         syncUpdate.accountData != null && |  | ||||||
|         syncUpdate.accountData! |  | ||||||
|             .any((accountData) => accountData.type == accountDataType)); |  | ||||||
|     await client.setAccountData( |     await client.setAccountData( | ||||||
|         client.userID!, accountDataType, content.toJson()); |         client.userID!, accountDataTypeKeyId, content.toJson()); | ||||||
|     await waitForAccountData; | 
 | ||||||
|  |     while (!client.accountData.containsKey(accountDataTypeKeyId)) { | ||||||
|  |       Logs().v('Waiting accountData to have $accountDataTypeKeyId'); | ||||||
|  |       await client.oneShotSync(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     final key = open(keyId); |     final key = open(keyId); | ||||||
|     await key.setPrivateKey(privateKey); |     await key.setPrivateKey(privateKey); | ||||||
|  | @ -327,7 +328,7 @@ class SSSS { | ||||||
|     } |     } | ||||||
|     final enc = encryptedContent.tryGetMap<String, Object?>(keyId); |     final enc = encryptedContent.tryGetMap<String, Object?>(keyId); | ||||||
|     if (enc == null) { |     if (enc == null) { | ||||||
|       throw Exception('Wrong / unknown key'); |       throw Exception('Wrong / unknown key: $type, $keyId'); | ||||||
|     } |     } | ||||||
|     final ciphertext = enc.tryGet<String>('ciphertext'); |     final ciphertext = enc.tryGet<String>('ciphertext'); | ||||||
|     final iv = enc.tryGet<String>('iv'); |     final iv = enc.tryGet<String>('iv'); | ||||||
|  | @ -750,6 +751,14 @@ class OpenSSSS { | ||||||
|       throw Exception('SSSS not unlocked'); |       throw Exception('SSSS not unlocked'); | ||||||
|     } |     } | ||||||
|     await ssss.store(type, secret, keyId, privateKey, add: add); |     await ssss.store(type, secret, keyId, privateKey, add: add); | ||||||
|  |     while (!ssss.client.accountData.containsKey(type) || | ||||||
|  |         !(ssss.client.accountData[type]!.content | ||||||
|  |             .tryGetMap<String, Object?>('encrypted')! | ||||||
|  |             .containsKey(keyId)) || | ||||||
|  |         await getStored(type) != secret) { | ||||||
|  |       Logs().d('Wait for secret of $type to match in accountdata'); | ||||||
|  |       await ssss.client.oneShotSync(); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   Future<void> validateAndStripOtherKeys(String type, String secret) async { |   Future<void> validateAndStripOtherKeys(String type, String secret) async { | ||||||
|  |  | ||||||
|  | @ -90,6 +90,8 @@ class Bootstrap { | ||||||
| 
 | 
 | ||||||
|   // cache the secret analyzing so that we don't drop stuff a different client sets during bootstrapping |   // cache the secret analyzing so that we don't drop stuff a different client sets during bootstrapping | ||||||
|   Map<String, Set<String>>? _secretsCache; |   Map<String, Set<String>>? _secretsCache; | ||||||
|  | 
 | ||||||
|  |   /// returns ssss from accountdata, eg: m.megolm_backup.v1, or your m.cross_signing stuff | ||||||
|   Map<String, Set<String>> analyzeSecrets() { |   Map<String, Set<String>> analyzeSecrets() { | ||||||
|     final secretsCache = _secretsCache; |     final secretsCache = _secretsCache; | ||||||
|     if (secretsCache != null) { |     if (secretsCache != null) { | ||||||
|  | @ -292,12 +294,12 @@ class Bootstrap { | ||||||
|         } |         } | ||||||
|         // alright, we re-encrypted all the secrets. We delete the dead weight only *after* we set our key to the default key |         // alright, we re-encrypted all the secrets. We delete the dead weight only *after* we set our key to the default key | ||||||
|       } |       } | ||||||
|       final updatedAccountData = client.onSync.stream.firstWhere((syncUpdate) => |  | ||||||
|           syncUpdate.accountData != null && |  | ||||||
|           syncUpdate.accountData!.any((accountData) => |  | ||||||
|               accountData.type == EventTypes.SecretStorageDefaultKey)); |  | ||||||
|       await encryption.ssss.setDefaultKeyId(newSsssKey!.keyId); |       await encryption.ssss.setDefaultKeyId(newSsssKey!.keyId); | ||||||
|       await updatedAccountData; |       while (encryption.ssss.defaultKeyId != newSsssKey!.keyId) { | ||||||
|  |         Logs().v( | ||||||
|  |             'Waiting accountData to have the correct m.secret_storage.default_key'); | ||||||
|  |         await client.oneShotSync(); | ||||||
|  |       } | ||||||
|       if (oldSsssKeys != null) { |       if (oldSsssKeys != null) { | ||||||
|         for (final entry in secretMap!.entries) { |         for (final entry in secretMap!.entries) { | ||||||
|           Logs().v('Validate and stripe other keys ${entry.key}...'); |           Logs().v('Validate and stripe other keys ${entry.key}...'); | ||||||
|  | @ -479,33 +481,23 @@ class Bootstrap { | ||||||
|               )); |               )); | ||||||
|       Logs().v('Device signing keys have been uploaded.'); |       Logs().v('Device signing keys have been uploaded.'); | ||||||
|       // aaaand set the SSSS secrets |       // aaaand set the SSSS secrets | ||||||
|       final futures = <Future<void>>[]; |  | ||||||
|       if (masterKey != null) { |       if (masterKey != null) { | ||||||
|         futures.add( |         while (!(masterKey.publicKey != null && | ||||||
|           client.onSync.stream |  | ||||||
|               .firstWhere((syncUpdate) => |  | ||||||
|                   masterKey?.publicKey != null && |  | ||||||
|             client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key == |             client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key == | ||||||
|                       masterKey?.publicKey) |                 masterKey.publicKey)) { | ||||||
|               .then((_) => Logs().v('New Master Key was created')), |           Logs().v('Waiting for master to be created'); | ||||||
|         ); |           await client.oneShotSync(); | ||||||
|         } |         } | ||||||
|  |       } | ||||||
|  |       if (newSsssKey != null) { | ||||||
|  |         final storeFutures = <Future<void>>[]; | ||||||
|         for (final entry in secretsToStore.entries) { |         for (final entry in secretsToStore.entries) { | ||||||
|         futures.add( |           storeFutures.add(newSsssKey!.store(entry.key, entry.value)); | ||||||
|           client.onSync.stream |  | ||||||
|               .firstWhere((syncUpdate) => |  | ||||||
|                   syncUpdate.accountData != null && |  | ||||||
|                   syncUpdate.accountData! |  | ||||||
|                       .any((accountData) => accountData.type == entry.key)) |  | ||||||
|               .then((_) => |  | ||||||
|                   Logs().v('New Key with type ${entry.key} was created')), |  | ||||||
|         ); |  | ||||||
|         Logs().v('Store new SSSS key ${entry.key}...'); |  | ||||||
|         await newSsssKey?.store(entry.key, entry.value); |  | ||||||
|         } |         } | ||||||
|       Logs().v( |         Logs().v('Store new SSSS key entries...'); | ||||||
|           'Wait for MasterKey and ${secretsToStore.entries.length} keys to be created'); |         await Future.wait(storeFutures); | ||||||
|       await Future.wait<void>(futures); |       } | ||||||
|  | 
 | ||||||
|       final keysToSign = <SignableKey>[]; |       final keysToSign = <SignableKey>[]; | ||||||
|       if (masterKey != null) { |       if (masterKey != null) { | ||||||
|         if (client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key != |         if (client.userDeviceKeys[client.userID]?.masterKey?.ed25519Key != | ||||||
|  | @ -581,14 +573,6 @@ class Bootstrap { | ||||||
|       ); |       ); | ||||||
|       Logs().v('Store the secret...'); |       Logs().v('Store the secret...'); | ||||||
|       await newSsssKey?.store(megolmKey, base64.encode(privKey)); |       await newSsssKey?.store(megolmKey, base64.encode(privKey)); | ||||||
|       Logs().v('Wait for secret to come down sync'); |  | ||||||
| 
 |  | ||||||
|       if (!await encryption.keyManager.isCached()) { |  | ||||||
|         await client.onSync.stream.firstWhere((syncUpdate) => |  | ||||||
|             syncUpdate.accountData != null && |  | ||||||
|             syncUpdate.accountData! |  | ||||||
|                 .any((accountData) => accountData.type == megolmKey)); |  | ||||||
|       } |  | ||||||
| 
 | 
 | ||||||
|       Logs().v( |       Logs().v( | ||||||
|           'And finally set all megolm keys as needing to be uploaded again...'); |           'And finally set all megolm keys as needing to be uploaded again...'); | ||||||
|  |  | ||||||
|  | @ -107,9 +107,12 @@ void main() { | ||||||
|       await handle.unlock(recoveryKey: ssssKey); |       await handle.unlock(recoveryKey: ssssKey); | ||||||
|       expect(handle.isUnlocked, true); |       expect(handle.isUnlocked, true); | ||||||
|       FakeMatrixApi.calledEndpoints.clear(); |       FakeMatrixApi.calledEndpoints.clear(); | ||||||
|       await handle.store('best animal', 'foxies'); | 
 | ||||||
|       // alright, since we don't properly sync we will manually have to update |       // OpenSSSS store waits for accountdata to be updated before returning | ||||||
|       // account_data for this test |       // but we can't update that before the below endpoint is not hit. | ||||||
|  |       await handle.ssss | ||||||
|  |           .store('best animal', 'foxies', handle.keyId, handle.privateKey!); | ||||||
|  | 
 | ||||||
|       final content = FakeMatrixApi |       final content = FakeMatrixApi | ||||||
|           .calledEndpoints[ |           .calledEndpoints[ | ||||||
|               '/client/v3/user/%40test%3AfakeServer.notExisting/account_data/best%20animal']! |               '/client/v3/user/%40test%3AfakeServer.notExisting/account_data/best%20animal']! | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue