Merge branch 'soru/key-verification-fixes' into 'master'

some key verification fixes and temporarily disable transactions

See merge request famedly/famedlysdk!403
This commit is contained in:
Christian Pauly 2020-07-30 08:33:44 +00:00
commit 5bf52664e1
4 changed files with 49 additions and 17 deletions

View file

@ -67,6 +67,10 @@ class KeyVerificationManager {
if (_requests.containsKey(transactionId)) { if (_requests.containsKey(transactionId)) {
await _requests[transactionId].handlePayload(event.type, event.content); await _requests[transactionId].handlePayload(event.type, event.content);
} else { } else {
if (!['m.key.verification.request', 'm.key.verification.start']
.contains(event.type)) {
return; // we can only start on these
}
final newKeyRequest = final newKeyRequest =
KeyVerification(encryption: encryption, userId: event.sender); KeyVerification(encryption: encryption, userId: event.sender);
await newKeyRequest.handlePayload(event.type, event.content); await newKeyRequest.handlePayload(event.type, event.content);
@ -111,6 +115,10 @@ class KeyVerificationManager {
_requests.remove(transactionId); _requests.remove(transactionId);
} }
} else if (event['sender'] != client.userID) { } 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) ?? final room = client.getRoomById(update.roomID) ??
Room(id: update.roomID, client: client); Room(id: update.roomID, client: client);
final newKeyRequest = KeyVerification( final newKeyRequest = KeyVerification(

View file

@ -215,7 +215,10 @@ class KeyVerification {
DateTime.fromMillisecondsSinceEpoch(payload['timestamp']); DateTime.fromMillisecondsSinceEpoch(payload['timestamp']);
if (now.subtract(Duration(minutes: 10)).isAfter(verifyTime) || if (now.subtract(Duration(minutes: 10)).isAfter(verifyTime) ||
now.add(Duration(minutes: 5)).isBefore(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; return;
} }
// verify it has a method we can use // verify it has a method we can use
@ -280,6 +283,13 @@ class KeyVerification {
} }
method = _makeVerificationMethod(payload['method'], this); method = _makeVerificationMethod(payload['method'], this);
if (lastStep == null) { 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)) { if (!method.validateStart(payload)) {
await cancel('m.unknown_method'); await cancel('m.unknown_method');
return; return;
@ -301,7 +311,11 @@ class KeyVerification {
setState(KeyVerificationState.error); setState(KeyVerificationState.error);
break; break;
default: default:
await method.handlePayload(type, payload); if (method != null) {
await method.handlePayload(type, payload);
} else {
await cancel('m.invalid_message');
}
break; break;
} }
if (lastStep == thisLastStep) { if (lastStep == thisLastStep) {
@ -310,9 +324,7 @@ class KeyVerification {
} catch (err, stacktrace) { } catch (err, stacktrace) {
print('[Key Verification] An error occured: ' + err.toString()); print('[Key Verification] An error occured: ' + err.toString());
print(stacktrace); print(stacktrace);
if (deviceId != null) { await cancel('m.invalid_message');
await cancel('m.invalid_message');
}
} finally { } finally {
_handlePayloadLock = false; _handlePayloadLock = false;
} }
@ -510,11 +522,13 @@ class KeyVerification {
return false; return false;
} }
Future<void> cancel([String code = 'm.unknown']) async { Future<void> cancel([String code = 'm.unknown', bool quiet = false]) async {
await send('m.key.verification.cancel', { if (!quiet && (deviceId != null || room != null)) {
'reason': code, await send('m.key.verification.cancel', {
'code': code, 'reason': code,
}); 'code': code,
});
}
canceled = true; canceled = true;
canceledCode = code; canceledCode = code;
setState(KeyVerificationState.error); setState(KeyVerificationState.error);
@ -538,7 +552,7 @@ class KeyVerification {
makePayload(payload); makePayload(payload);
print('[Key Verification] Sending type ${type}: ' + payload.toString()); print('[Key Verification] Sending type ${type}: ' + payload.toString());
if (room != null) { 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)) { if (['m.key.verification.request'].contains(type)) {
payload['msgtype'] = type; payload['msgtype'] = type;
payload['to'] = userId; payload['to'] = userId;
@ -552,7 +566,7 @@ class KeyVerification {
encryption.keyVerificationManager.addRequest(this); encryption.keyVerificationManager.addRequest(this);
} }
} else { } else {
print('[Key Verification] Sending to ${userId} device ${deviceId}'); print('[Key Verification] Sending to ${userId} device ${deviceId}...');
await client.sendToDevice( await client.sendToDevice(
[client.userDeviceKeys[userId].deviceKeys[deviceId]], type, payload); [client.userDeviceKeys[userId].deviceKeys[deviceId]], type, payload);
} }

View file

@ -1331,11 +1331,14 @@ class Client {
} }
} }
} }
await database?.transaction(() async {
for (final f in dbActions) { if (dbActions.isNotEmpty) {
await f(); await database?.transaction(() async {
} for (final f in dbActions) {
}); await f();
}
});
}
} catch (e) { } catch (e) {
print('[LibOlm] Unable to update user device keys: ' + e.toString()); print('[LibOlm] Unable to update user device keys: ' + e.toString());
} }

View file

@ -22,6 +22,13 @@ class Database extends _$Database {
int get maxFileSize => 1 * 1024 * 1024; 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<T> transaction<T>(Future<T> Function() action) async {
return action();
}
@override @override
MigrationStrategy get migration => MigrationStrategy( MigrationStrategy get migration => MigrationStrategy(
onCreate: (Migrator m) { onCreate: (Migrator m) {