feat: Implement enabling and disabling devices

This commit is contained in:
PapaTutuWawa 2022-09-11 12:34:31 +02:00
parent d530358359
commit 12e09947f6
6 changed files with 59 additions and 4 deletions

View File

@ -254,6 +254,9 @@ class OmemoSessionManager {
if (plaintext != null) { if (plaintext != null) {
// Only encrypt to devices that are trusted // Only encrypt to devices that are trusted
if (!(await _trustManager.isTrusted(jid, deviceId))) continue; if (!(await _trustManager.isTrusted(jid, deviceId))) continue;
// Onyl encrypt to devices that are enabled
if (!(await _trustManager.isEnabled(jid, deviceId))) continue;
} }
final ratchetKey = RatchetMapKey(jid, deviceId); final ratchetKey = RatchetMapKey(jid, deviceId);

View File

@ -11,4 +11,10 @@ class AlwaysTrustingTrustManager extends TrustManager {
@override @override
Future<void> onNewSession(String jid, int deviceId) async {} Future<void> onNewSession(String jid, int deviceId) async {}
@override
Future<bool> isEnabled(String jid, int deviceId) async => true;
@override
Future<void> setEnabled(String jid, int deviceId, bool enabled) async {}
} }

View File

@ -8,4 +8,12 @@ abstract class TrustManager {
/// Called by the OmemoSessionManager when a new session has been built. Should set /// Called by the OmemoSessionManager when a new session has been built. Should set
/// a default trust state to [jid]'s device with identifier [deviceId]. /// a default trust state to [jid]'s device with identifier [deviceId].
Future<void> onNewSession(String jid, int deviceId); Future<void> onNewSession(String jid, int deviceId);
/// Return true if the device with id [deviceId] of Jid [jid] should be used for encryption.
/// If not, return false.
Future<bool> isEnabled(String jid, int deviceId);
/// Mark the device with id [deviceId] of Jid [jid] as enabled if [enabled] is true or as disabled
/// if [enabled] is false.
Future<void> setEnabled(String jid, int deviceId, bool enabled);
} }

View File

@ -18,13 +18,18 @@ enum BTBVTrustState {
abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager { abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
BlindTrustBeforeVerificationTrustManager() BlindTrustBeforeVerificationTrustManager()
: trustCache = {}, : trustCache = {},
enablementCache = {},
devices = {}, devices = {},
_lock = Lock(); _lock = Lock();
/// The cache for Mapping a RatchetMapKey to its trust state /// The cache for mapping a RatchetMapKey to its trust state
@protected @protected
final Map<RatchetMapKey, BTBVTrustState> trustCache; final Map<RatchetMapKey, BTBVTrustState> trustCache;
/// The cache for mapping a RatchetMapKey to whether it is enabled or not
@protected
final Map<RatchetMapKey, bool> enablementCache;
/// Mapping of Jids to their device identifiers /// Mapping of Jids to their device identifiers
@protected @protected
final Map<String, List<int>> devices; final Map<String, List<int>> devices;
@ -74,10 +79,13 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
@override @override
Future<void> onNewSession(String jid, int deviceId) async { Future<void> onNewSession(String jid, int deviceId) async {
await _lock.synchronized(() async { await _lock.synchronized(() async {
final key = RatchetMapKey(jid, deviceId);
if (_hasAtLeastOneVerifiedDevice(jid)) { if (_hasAtLeastOneVerifiedDevice(jid)) {
trustCache[RatchetMapKey(jid, deviceId)] = BTBVTrustState.notTrusted; trustCache[key] = BTBVTrustState.notTrusted;
enablementCache[key] = false;
} else { } else {
trustCache[RatchetMapKey(jid, deviceId)] = BTBVTrustState.blindTrust; trustCache[key] = BTBVTrustState.blindTrust;
enablementCache[key] = true;
} }
if (devices.containsKey(jid)) { if (devices.containsKey(jid)) {
@ -85,7 +93,7 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
} else { } else {
devices[jid] = List<int>.from([deviceId]); devices[jid] = List<int>.from([deviceId]);
} }
// Commit the state // Commit the state
await commitState(); await commitState();
}); });
@ -114,6 +122,26 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
}); });
} }
@override
Future<bool> isEnabled(String jid, int deviceId) async {
return _lock.synchronized(() async {
final value = enablementCache[RatchetMapKey(jid, deviceId)];
if (value == null) return false;
return value;
});
}
@override
Future<void> setEnabled(String jid, int deviceId, bool enabled) async {
await _lock.synchronized(() async {
enablementCache[RatchetMapKey(jid, deviceId)] = enabled;
});
// Commit the state
await commitState();
}
/// Called when the state of the trust manager has been changed. Allows the user to /// Called when the state of the trust manager has been changed. Allows the user to
/// commit the trust state to persistent storage. /// commit the trust state to persistent storage.
@visibleForOverriding @visibleForOverriding

View File

@ -11,4 +11,10 @@ class NeverTrustingTrustManager extends TrustManager {
@override @override
Future<void> onNewSession(String jid, int deviceId) async {} Future<void> onNewSession(String jid, int deviceId) async {}
@override
Future<bool> isEnabled(String jid, int deviceId) async => true;
@override
Future<void> setEnabled(String jid, int deviceId, bool enabled) async {}
} }

View File

@ -12,6 +12,7 @@ void main() {
// Caroline starts a chat a device from Alice // Caroline starts a chat a device from Alice
await btbv.onNewSession(aliceJid, 1); await btbv.onNewSession(aliceJid, 1);
expect(await btbv.isTrusted(aliceJid, 1), true); expect(await btbv.isTrusted(aliceJid, 1), true);
expect(await btbv.isEnabled(aliceJid, 1), true);
// Caroline meets with Alice and verifies her fingerprint // Caroline meets with Alice and verifies her fingerprint
await btbv.setDeviceTrust(aliceJid, 1, BTBVTrustState.verified); await btbv.setDeviceTrust(aliceJid, 1, BTBVTrustState.verified);
@ -21,6 +22,7 @@ void main() {
await btbv.onNewSession(aliceJid, 2); await btbv.onNewSession(aliceJid, 2);
expect(await btbv.isTrusted(aliceJid, 2), false); expect(await btbv.isTrusted(aliceJid, 2), false);
expect(btbv.getDeviceTrust(aliceJid, 2), BTBVTrustState.notTrusted); expect(btbv.getDeviceTrust(aliceJid, 2), BTBVTrustState.notTrusted);
expect(await btbv.isEnabled(aliceJid, 2), false);
// Caronline starts a chat with Bob but since they live far apart, Caroline cannot // Caronline starts a chat with Bob but since they live far apart, Caroline cannot
// verify his fingerprint. // verify his fingerprint.
@ -32,5 +34,7 @@ void main() {
expect(await btbv.isTrusted(bobJid, 4), true); expect(await btbv.isTrusted(bobJid, 4), true);
expect(btbv.getDeviceTrust(bobJid, 3), BTBVTrustState.blindTrust); expect(btbv.getDeviceTrust(bobJid, 3), BTBVTrustState.blindTrust);
expect(btbv.getDeviceTrust(bobJid, 4), BTBVTrustState.blindTrust); expect(btbv.getDeviceTrust(bobJid, 4), BTBVTrustState.blindTrust);
expect(await btbv.isEnabled(bobJid, 3), true);
expect(await btbv.isEnabled(bobJid, 4), true);
}); });
} }