diff --git a/lib/encryption/key_verification_manager.dart b/lib/encryption/key_verification_manager.dart index de82074..d02d107 100644 --- a/lib/encryption/key_verification_manager.dart +++ b/lib/encryption/key_verification_manager.dart @@ -67,6 +67,10 @@ class KeyVerificationManager { if (_requests.containsKey(transactionId)) { await _requests[transactionId].handlePayload(event.type, event.content); } else { + if (!['m.key.verification.request', 'm.key.verification.start'] + .contains(event.type)) { + return; // we can only start on these + } final newKeyRequest = KeyVerification(encryption: encryption, userId: event.sender); await newKeyRequest.handlePayload(event.type, event.content); @@ -111,6 +115,10 @@ class KeyVerificationManager { _requests.remove(transactionId); } } else if (event['sender'] != client.userID) { + if (!['m.key.verification.request', 'm.key.verification.start'] + .contains(type)) { + return; // we can only start on these + } final room = client.getRoomById(update.roomID) ?? Room(id: update.roomID, client: client); final newKeyRequest = KeyVerification( diff --git a/lib/encryption/utils/key_verification.dart b/lib/encryption/utils/key_verification.dart index e4a43f3..fbcab32 100644 --- a/lib/encryption/utils/key_verification.dart +++ b/lib/encryption/utils/key_verification.dart @@ -215,7 +215,10 @@ class KeyVerification { DateTime.fromMillisecondsSinceEpoch(payload['timestamp']); if (now.subtract(Duration(minutes: 10)).isAfter(verifyTime) || now.add(Duration(minutes: 5)).isBefore(verifyTime)) { - await cancel('m.timeout'); + // if the request is more than 20min in the past we just silently fail it + // to not generate too many cancels + await cancel('m.timeout', + now.subtract(Duration(minutes: 20)).isAfter(verifyTime)); return; } // verify it has a method we can use @@ -280,6 +283,13 @@ class KeyVerification { } method = _makeVerificationMethod(payload['method'], this); if (lastStep == null) { + // validate the start time + if (room != null) { + // we just silently ignore in-room-verification starts + await cancel('m.unknown_method', true); + return; + } + // validate the specific payload if (!method.validateStart(payload)) { await cancel('m.unknown_method'); return; @@ -301,7 +311,11 @@ class KeyVerification { setState(KeyVerificationState.error); break; default: - await method.handlePayload(type, payload); + if (method != null) { + await method.handlePayload(type, payload); + } else { + await cancel('m.invalid_message'); + } break; } if (lastStep == thisLastStep) { @@ -310,9 +324,7 @@ class KeyVerification { } catch (err, stacktrace) { print('[Key Verification] An error occured: ' + err.toString()); print(stacktrace); - if (deviceId != null) { - await cancel('m.invalid_message'); - } + await cancel('m.invalid_message'); } finally { _handlePayloadLock = false; } @@ -510,11 +522,13 @@ class KeyVerification { return false; } - Future cancel([String code = 'm.unknown']) async { - await send('m.key.verification.cancel', { - 'reason': code, - 'code': code, - }); + Future cancel([String code = 'm.unknown', bool quiet = false]) async { + if (!quiet && (deviceId != null || room != null)) { + await send('m.key.verification.cancel', { + 'reason': code, + 'code': code, + }); + } canceled = true; canceledCode = code; setState(KeyVerificationState.error); @@ -538,7 +552,7 @@ class KeyVerification { makePayload(payload); print('[Key Verification] Sending type ${type}: ' + payload.toString()); if (room != null) { - print('[Key Verification] Sending to ${userId} in room ${room.id}'); + print('[Key Verification] Sending to ${userId} in room ${room.id}...'); if (['m.key.verification.request'].contains(type)) { payload['msgtype'] = type; payload['to'] = userId; @@ -552,7 +566,7 @@ class KeyVerification { encryption.keyVerificationManager.addRequest(this); } } else { - print('[Key Verification] Sending to ${userId} device ${deviceId}'); + print('[Key Verification] Sending to ${userId} device ${deviceId}...'); await client.sendToDevice( [client.userDeviceKeys[userId].deviceKeys[deviceId]], type, payload); } diff --git a/lib/src/client.dart b/lib/src/client.dart index 44ad73b..6243ca4 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -1331,11 +1331,14 @@ class Client { } } } - await database?.transaction(() async { - for (final f in dbActions) { - await f(); - } - }); + + if (dbActions.isNotEmpty) { + await database?.transaction(() async { + for (final f in dbActions) { + await f(); + } + }); + } } catch (e) { print('[LibOlm] Unable to update user device keys: ' + e.toString()); } diff --git a/lib/src/database/database.dart b/lib/src/database/database.dart index adb9fc6..3b148ec 100644 --- a/lib/src/database/database.dart +++ b/lib/src/database/database.dart @@ -22,6 +22,13 @@ class Database extends _$Database { int get maxFileSize => 1 * 1024 * 1024; + // moor transactions are sometimes rather weird and freeze. Until there is a + // proper fix in moor we override that there aren't actually using transactions + @override + Future transaction(Future Function() action) async { + return action(); + } + @override MigrationStrategy get migration => MigrationStrategy( onCreate: (Migrator m) {