feat: Add broadcast to-device verification
This commit is contained in:
parent
f9f18641e3
commit
5924e57cf1
|
|
@ -563,6 +563,7 @@ class KeyManager {
|
|||
stacktrace);
|
||||
}
|
||||
}
|
||||
// TODO: also don't request from others if we have an index of 0 now
|
||||
if (!hadPreviously &&
|
||||
getInboundGroupSession(room.id, sessionId, senderKey) != null) {
|
||||
return; // we managed to load the session from online backup, no need to care about it now
|
||||
|
|
|
|||
|
|
@ -65,9 +65,12 @@ class KeyVerificationManager {
|
|||
return; // TODO: send cancel with unknown transaction id
|
||||
}
|
||||
if (_requests.containsKey(transactionId)) {
|
||||
await _requests[transactionId].handlePayload(event.type, event.content);
|
||||
// make sure that new requests can't come from ourself
|
||||
if (!{'m.key.verification.request'}.contains(event.type)) {
|
||||
await _requests[transactionId].handlePayload(event.type, event.content);
|
||||
}
|
||||
} else {
|
||||
if (!['m.key.verification.request', 'm.key.verification.start']
|
||||
if (!{'m.key.verification.request', 'm.key.verification.start'}
|
||||
.contains(event.type)) {
|
||||
return; // we can only start on these
|
||||
}
|
||||
|
|
@ -115,7 +118,7 @@ class KeyVerificationManager {
|
|||
_requests.remove(transactionId);
|
||||
}
|
||||
} else if (event['sender'] != client.userID) {
|
||||
if (!['m.key.verification.request', 'm.key.verification.start']
|
||||
if (!{'m.key.verification.request', 'm.key.verification.start'}
|
||||
.contains(type)) {
|
||||
return; // we can only start on these
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,6 +140,9 @@ class KeyVerification {
|
|||
bool canceled = false;
|
||||
String canceledCode;
|
||||
String canceledReason;
|
||||
bool get isDone =>
|
||||
canceled ||
|
||||
{KeyVerificationState.error, KeyVerificationState.done}.contains(state);
|
||||
|
||||
KeyVerification(
|
||||
{this.encryption,
|
||||
|
|
@ -200,6 +203,9 @@ class KeyVerification {
|
|||
|
||||
Future<void> handlePayload(String type, Map<String, dynamic> payload,
|
||||
[String eventId]) async {
|
||||
if (isDone) {
|
||||
return; // no need to do anything with already canceled requests
|
||||
}
|
||||
while (_handlePayloadLock) {
|
||||
await Future.delayed(Duration(milliseconds: 50));
|
||||
}
|
||||
|
|
@ -235,6 +241,21 @@ class KeyVerification {
|
|||
setState(KeyVerificationState.askAccept);
|
||||
break;
|
||||
case 'm.key.verification.ready':
|
||||
if (deviceId == '*') {
|
||||
_deviceId = payload['from_device']; // gotta set the real device id
|
||||
// and broadcast the cancel to the other devices
|
||||
final devices = List<DeviceKeys>.from(
|
||||
client.userDeviceKeys[userId].deviceKeys.values);
|
||||
devices.removeWhere(
|
||||
(d) => {deviceId, client.deviceID}.contains(d.deviceId));
|
||||
final cancelPayload = <String, dynamic>{
|
||||
'reason': 'Another device accepted the request',
|
||||
'code': 'm.accepted',
|
||||
};
|
||||
makePayload(cancelPayload);
|
||||
await client.sendToDeviceEncrypted(
|
||||
devices, 'm.key.verification.cancel', cancelPayload);
|
||||
}
|
||||
_deviceId ??= payload['from_device'];
|
||||
possibleMethods =
|
||||
_intersect(knownVerificationMethods, payload['methods']);
|
||||
|
|
@ -383,6 +404,9 @@ class KeyVerification {
|
|||
|
||||
/// called when the user rejects an incoming verification
|
||||
Future<void> rejectVerification() async {
|
||||
if (isDone) {
|
||||
return;
|
||||
}
|
||||
if (!(await verifyLastStep(
|
||||
['m.key.verification.request', 'm.key.verification.start']))) {
|
||||
return;
|
||||
|
|
@ -557,7 +581,7 @@ class KeyVerification {
|
|||
if (room != null) {
|
||||
Logs.info(
|
||||
'[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['to'] = userId;
|
||||
payload['body'] =
|
||||
|
|
@ -572,8 +596,19 @@ class KeyVerification {
|
|||
} else {
|
||||
Logs.info(
|
||||
'[Key Verification] Sending to ${userId} device ${deviceId}...');
|
||||
await client.sendToDeviceEncrypted(
|
||||
[client.userDeviceKeys[userId].deviceKeys[deviceId]], type, payload);
|
||||
if (deviceId == '*') {
|
||||
if ({'m.key.verification.request'}.contains(type)) {
|
||||
await client.sendToDevicesOfUserIds({userId}, type, payload);
|
||||
} else {
|
||||
Logs.error(
|
||||
'[Key Verification] Tried to broadcast and un-broadcastable type: ${type}');
|
||||
}
|
||||
} else {
|
||||
await client.sendToDeviceEncrypted(
|
||||
[client.userDeviceKeys[userId].deviceKeys[deviceId]],
|
||||
type,
|
||||
payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,18 +54,29 @@ class DeviceKeysList {
|
|||
}
|
||||
|
||||
Future<KeyVerification> startVerification() async {
|
||||
final roomId =
|
||||
await User(userId, room: Room(client: client)).startDirectChat();
|
||||
if (roomId == null) {
|
||||
throw 'Unable to start new room';
|
||||
if (userId != client.userID) {
|
||||
// in-room verification with someone else
|
||||
final roomId =
|
||||
await User(userId, room: Room(client: client)).startDirectChat();
|
||||
if (roomId == null) {
|
||||
throw 'Unable to start new room';
|
||||
}
|
||||
final room =
|
||||
client.getRoomById(roomId) ?? Room(id: roomId, client: client);
|
||||
final request = KeyVerification(
|
||||
encryption: client.encryption, room: room, userId: userId);
|
||||
await request.start();
|
||||
// no need to add to the request client object. As we are doing a room
|
||||
// verification request that'll happen automatically once we know the transaction id
|
||||
return request;
|
||||
} else {
|
||||
// broadcast self-verification
|
||||
final request = KeyVerification(
|
||||
encryption: client.encryption, userId: userId, deviceId: '*');
|
||||
await request.start();
|
||||
client.encryption.keyVerificationManager.addRequest(request);
|
||||
return request;
|
||||
}
|
||||
final room = client.getRoomById(roomId) ?? Room(id: roomId, client: client);
|
||||
final request = KeyVerification(
|
||||
encryption: client.encryption, room: room, userId: userId);
|
||||
await request.start();
|
||||
// no need to add to the request client object. As we are doing a room
|
||||
// verification request that'll happen automatically once we know the transaction id
|
||||
return request;
|
||||
}
|
||||
|
||||
DeviceKeysList.fromDb(
|
||||
|
|
|
|||
Loading…
Reference in New Issue