also restore on broken olm session

This commit is contained in:
Sorunome 2020-06-23 11:35:43 +02:00
parent f833511e38
commit b109e75962
No known key found for this signature in database
GPG key ID: B19471D07FC9BE9C
2 changed files with 47 additions and 6 deletions

View file

@ -18,6 +18,7 @@
import 'dart:convert'; import 'dart:convert';
import 'package:pedantic/pedantic.dart';
import 'package:canonical_json/canonical_json.dart'; import 'package:canonical_json/canonical_json.dart';
import 'package:famedlysdk/famedlysdk.dart'; import 'package:famedlysdk/famedlysdk.dart';
import 'package:famedlysdk/matrix_api.dart'; import 'package:famedlysdk/matrix_api.dart';
@ -323,6 +324,19 @@ class OlmManager {
return res; return res;
} }
Future<void> restoreOlmSession(String userId, String senderKey) async {
if (!client.userDeviceKeys.containsKey(userId)) {
return;
}
final device = client.userDeviceKeys[userId].deviceKeys.values
.firstWhere((d) => d.curve25519Key == senderKey, orElse: () => null);
if (device == null) {
return;
}
await startOutgoingOlmSessions([device]);
await client.sendToDevice([device], 'm.dummy', {});
}
Future<ToDeviceEvent> decryptToDeviceEvent(ToDeviceEvent event) async { Future<ToDeviceEvent> decryptToDeviceEvent(ToDeviceEvent event) async {
if (event.type != EventTypes.Encrypted) { if (event.type != EventTypes.Encrypted) {
return event; return event;
@ -342,12 +356,20 @@ class OlmManager {
if (!_olmSessions.containsKey(senderKey)) { if (!_olmSessions.containsKey(senderKey)) {
await loadFromDb(); await loadFromDb();
} }
event = _decryptToDeviceEvent(event); try {
if (event.type != EventTypes.Encrypted || !(await loadFromDb())) { event = _decryptToDeviceEvent(event);
return event; if (event.type != EventTypes.Encrypted || !(await loadFromDb())) {
return event;
}
// retry to decrypt!
return _decryptToDeviceEvent(event);
} catch (_) {
// okay, the thing errored while decrypting. It is safe to assume that the olm session is corrupt and we should generate a new one
if (client.enableE2eeRecovery) {
unawaited(restoreOlmSession(event.senderId, senderKey));
}
rethrow;
} }
// retry to decrypt!
return _decryptToDeviceEvent(event);
} }
Future<void> startOutgoingOlmSessions(List<DeviceKeys> deviceKeys) async { Future<void> startOutgoingOlmSessions(List<DeviceKeys> deviceKeys) async {
@ -383,7 +405,8 @@ class OlmManager {
identityKey: identityKey, identityKey: identityKey,
sessionId: session.session_id(), sessionId: session.session_id(),
session: session, session: session,
lastReceived: DateTime.fromMillisecondsSinceEpoch(0), lastReceived:
DateTime.now(), // we want to use a newly created session
)); ));
} catch (e) { } catch (e) {
session.free(); session.free();

View file

@ -99,8 +99,26 @@ void main() {
false); false);
}); });
test('restoreOlmSession', () async {
client.encryption.olmManager.olmSessions.clear();
await client.encryption.olmManager
.restoreOlmSession(client.userID, client.identityKey);
expect(client.encryption.olmManager.olmSessions.length, 1);
client.encryption.olmManager.olmSessions.clear();
await client.encryption.olmManager
.restoreOlmSession(client.userID, 'invalid');
expect(client.encryption.olmManager.olmSessions.length, 0);
client.encryption.olmManager.olmSessions.clear();
await client.encryption.olmManager
.restoreOlmSession('invalid', client.identityKey);
expect(client.encryption.olmManager.olmSessions.length, 0);
});
test('startOutgoingOlmSessions', () async { test('startOutgoingOlmSessions', () async {
// start an olm session.....with ourself! // start an olm session.....with ourself!
client.encryption.olmManager.olmSessions.clear();
await client.encryption.olmManager.startOutgoingOlmSessions( await client.encryption.olmManager.startOutgoingOlmSessions(
[client.userDeviceKeys[client.userID].deviceKeys[client.deviceID]]); [client.userDeviceKeys[client.userID].deviceKeys[client.deviceID]]);
expect( expect(