3 Commits

7 changed files with 61 additions and 12 deletions

View File

@@ -254,6 +254,9 @@ class OmemoSessionManager {
if (plaintext != null) {
// Only encrypt to devices that are trusted
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);
@@ -415,13 +418,7 @@ class OmemoSessionManager {
/// Returns the device map, i.e. the mapping of bare Jid to its device identifiers
/// we have built sessions with.
Future<Map<String, List<int>>> getDeviceMap() async {
Map<String, List<int>>? map;
await _lock.synchronized(() async {
map = _deviceMap;
});
return map!;
return _lock.synchronized(() => _deviceMap);
}
/// Removes the ratchet identified by [jid] and [deviceId] from the session manager.

View File

@@ -11,4 +11,10 @@ class AlwaysTrustingTrustManager extends TrustManager {
@override
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
/// a default trust state to [jid]'s device with identifier [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 {
BlindTrustBeforeVerificationTrustManager()
: trustCache = {},
enablementCache = {},
devices = {},
_lock = Lock();
/// The cache for Mapping a RatchetMapKey to its trust state
/// The cache for mapping a RatchetMapKey to its trust state
@protected
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
@protected
final Map<String, List<int>> devices;
@@ -74,10 +79,13 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
@override
Future<void> onNewSession(String jid, int deviceId) async {
await _lock.synchronized(() async {
final key = RatchetMapKey(jid, deviceId);
if (_hasAtLeastOneVerifiedDevice(jid)) {
trustCache[RatchetMapKey(jid, deviceId)] = BTBVTrustState.notTrusted;
trustCache[key] = BTBVTrustState.notTrusted;
enablementCache[key] = false;
} else {
trustCache[RatchetMapKey(jid, deviceId)] = BTBVTrustState.blindTrust;
trustCache[key] = BTBVTrustState.blindTrust;
enablementCache[key] = true;
}
if (devices.containsKey(jid)) {
@@ -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
/// commit the trust state to persistent storage.
@visibleForOverriding

View File

@@ -11,4 +11,10 @@ class NeverTrustingTrustManager extends TrustManager {
@override
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

@@ -11,7 +11,7 @@ dependencies:
collection: ^1.16.0
cryptography: ^2.0.5
hex: ^0.2.0
meta: ^1.8.0
meta: ^1.7.0
pinenacl: ^0.5.1
synchronized: ^3.0.0+2

View File

@@ -12,6 +12,7 @@ void main() {
// Caroline starts a chat a device from Alice
await btbv.onNewSession(aliceJid, 1);
expect(await btbv.isTrusted(aliceJid, 1), true);
expect(await btbv.isEnabled(aliceJid, 1), true);
// Caroline meets with Alice and verifies her fingerprint
await btbv.setDeviceTrust(aliceJid, 1, BTBVTrustState.verified);
@@ -21,6 +22,7 @@ void main() {
await btbv.onNewSession(aliceJid, 2);
expect(await btbv.isTrusted(aliceJid, 2), false);
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
// verify his fingerprint.
@@ -32,5 +34,7 @@ void main() {
expect(await btbv.isTrusted(bobJid, 4), true);
expect(btbv.getDeviceTrust(bobJid, 3), BTBVTrustState.blindTrust);
expect(btbv.getDeviceTrust(bobJid, 4), BTBVTrustState.blindTrust);
expect(await btbv.isEnabled(bobJid, 3), true);
expect(await btbv.isEnabled(bobJid, 4), true);
});
}