feat: Stop overriding the BTBV manager
This commit is contained in:
parent
28e7ad59b0
commit
4fb25a3ab7
@ -42,7 +42,7 @@ void main() async {
|
|||||||
// request it using PEP and then convert the device bundle into a OmemoBundle object.
|
// request it using PEP and then convert the device bundle into a OmemoBundle object.
|
||||||
final bobManager = OmemoManager(
|
final bobManager = OmemoManager(
|
||||||
await OmemoDevice.generateNewDevice(bobJid),
|
await OmemoDevice.generateNewDevice(bobJid),
|
||||||
MemoryBTBVTrustManager(),
|
BlindTrustBeforeVerificationTrustManager(),
|
||||||
(result, recipient) async => {},
|
(result, recipient) async => {},
|
||||||
(jid) async => [],
|
(jid) async => [],
|
||||||
(jid, id) async => null,
|
(jid, id) async => null,
|
||||||
|
@ -20,7 +20,4 @@ class AlwaysTrustingTrustManager extends TrustManager {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> removeTrustDecisionsForJid(String jid) async {}
|
Future<void> removeTrustDecisionsForJid(String jid) async {}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Map<String, dynamic>> toJson() async => <String, dynamic>{};
|
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,6 @@ abstract class TrustManager {
|
|||||||
/// if [enabled] is false.
|
/// if [enabled] is false.
|
||||||
Future<void> setEnabled(String jid, int deviceId, bool enabled);
|
Future<void> setEnabled(String jid, int deviceId, bool enabled);
|
||||||
|
|
||||||
/// Serialize the trust manager to JSON.
|
|
||||||
Future<Map<String, dynamic>> toJson();
|
|
||||||
|
|
||||||
/// Removes all trust decisions for [jid].
|
/// Removes all trust decisions for [jid].
|
||||||
Future<void> removeTrustDecisionsForJid(String jid);
|
Future<void> removeTrustDecisionsForJid(String jid);
|
||||||
}
|
}
|
||||||
|
@ -3,47 +3,64 @@ import 'package:omemo_dart/src/omemo/ratchet_map_key.dart';
|
|||||||
import 'package:omemo_dart/src/trust/base.dart';
|
import 'package:omemo_dart/src/trust/base.dart';
|
||||||
import 'package:synchronized/synchronized.dart';
|
import 'package:synchronized/synchronized.dart';
|
||||||
|
|
||||||
|
@immutable
|
||||||
|
class BTBVTrustData {
|
||||||
|
const BTBVTrustData(
|
||||||
|
this.jid,
|
||||||
|
this.device,
|
||||||
|
this.state,
|
||||||
|
this.enabled,
|
||||||
|
);
|
||||||
|
|
||||||
|
/// The JID in question.
|
||||||
|
final String jid;
|
||||||
|
|
||||||
|
/// The device (ratchet) in question.
|
||||||
|
final int device;
|
||||||
|
|
||||||
|
/// The trust state of the ratchet.
|
||||||
|
final BTBVTrustState state;
|
||||||
|
|
||||||
|
/// Flag indicating whether the ratchet is enabled (true) or not (false).
|
||||||
|
final bool enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A callback for when a trust decision is to be commited to persistent storage.
|
||||||
|
typedef BTBVTrustCommitCallback = Future<void> Function(BTBVTrustData data);
|
||||||
|
|
||||||
|
/// A stub-implementation of [BTBVTrustCommitCallback].
|
||||||
|
Future<void> btbvCommitStub(BTBVTrustData _) async {}
|
||||||
|
|
||||||
|
/// A callback for when all trust decisions for a JID should be removed from persistent storage.
|
||||||
|
typedef BTBVRemoveTrustForJidCallback = Future<void> Function(String jid);
|
||||||
|
|
||||||
|
/// A stub-implementation of [BTBVRemoveTrustForJidCallback].
|
||||||
|
Future<void> btbvRemoveTrustStub(String _) async {}
|
||||||
|
|
||||||
/// Every device is in either of those two trust states:
|
/// Every device is in either of those two trust states:
|
||||||
/// - notTrusted: The device is absolutely not trusted
|
/// - notTrusted: The device is absolutely not trusted
|
||||||
/// - blindTrust: The fingerprint is not verified using OOB means
|
/// - blindTrust: The fingerprint is not verified using OOB means
|
||||||
/// - verified: The fingerprint has been verified using OOB means
|
/// - verified: The fingerprint has been verified using OOB means
|
||||||
enum BTBVTrustState {
|
enum BTBVTrustState {
|
||||||
notTrusted, // = 1
|
notTrusted(1),
|
||||||
blindTrust, // = 2
|
blindTrust(2),
|
||||||
verified, // = 3
|
verified(3);
|
||||||
}
|
|
||||||
|
|
||||||
int _trustToInt(BTBVTrustState state) {
|
const BTBVTrustState(this.value);
|
||||||
switch (state) {
|
|
||||||
case BTBVTrustState.notTrusted:
|
|
||||||
return 1;
|
|
||||||
case BTBVTrustState.blindTrust:
|
|
||||||
return 2;
|
|
||||||
case BTBVTrustState.verified:
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BTBVTrustState _trustFromInt(int i) {
|
/// The value backing the trust state.
|
||||||
switch (i) {
|
final int value;
|
||||||
case 1:
|
|
||||||
return BTBVTrustState.notTrusted;
|
|
||||||
case 2:
|
|
||||||
return BTBVTrustState.blindTrust;
|
|
||||||
case 3:
|
|
||||||
return BTBVTrustState.verified;
|
|
||||||
default:
|
|
||||||
return BTBVTrustState.notTrusted;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A TrustManager that implements the idea of Blind Trust Before Verification.
|
/// A TrustManager that implements the idea of Blind Trust Before Verification.
|
||||||
/// See https://gultsch.de/trust.html for more details.
|
/// See https://gultsch.de/trust.html for more details.
|
||||||
abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
||||||
BlindTrustBeforeVerificationTrustManager({
|
BlindTrustBeforeVerificationTrustManager({
|
||||||
Map<RatchetMapKey, BTBVTrustState>? trustCache,
|
Map<RatchetMapKey, BTBVTrustState>? trustCache,
|
||||||
Map<RatchetMapKey, bool>? enablementCache,
|
Map<RatchetMapKey, bool>? enablementCache,
|
||||||
Map<String, List<int>>? devices,
|
Map<String, List<int>>? devices,
|
||||||
|
this.commit = btbvCommitStub,
|
||||||
|
this.removeTrust = btbvRemoveTrustStub,
|
||||||
}) : trustCache = trustCache ?? {},
|
}) : trustCache = trustCache ?? {},
|
||||||
enablementCache = enablementCache ?? {},
|
enablementCache = enablementCache ?? {},
|
||||||
devices = devices ?? {},
|
devices = devices ?? {},
|
||||||
@ -67,6 +84,12 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
|||||||
/// The lock for devices and trustCache
|
/// The lock for devices and trustCache
|
||||||
final Lock _lock;
|
final Lock _lock;
|
||||||
|
|
||||||
|
/// Callback for commiting trust data to persistent storage.
|
||||||
|
final BTBVTrustCommitCallback commit;
|
||||||
|
|
||||||
|
/// Callback for removing trust data for a JID.
|
||||||
|
final BTBVRemoveTrustForJidCallback removeTrust;
|
||||||
|
|
||||||
/// Returns true if [jid] has at least one device that is verified. If not, returns false.
|
/// Returns true if [jid] has at least one device that is verified. If not, returns false.
|
||||||
/// Note that this function accesses devices and trustCache, which requires that the
|
/// Note that this function accesses devices and trustCache, which requires that the
|
||||||
/// lock for those two maps (_lock) has been aquired before calling.
|
/// lock for those two maps (_lock) has been aquired before calling.
|
||||||
@ -125,7 +148,14 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Commit the state
|
// Commit the state
|
||||||
await commitState();
|
await commit(
|
||||||
|
BTBVTrustData(
|
||||||
|
jid,
|
||||||
|
deviceId,
|
||||||
|
trustCache[key]!,
|
||||||
|
enablementCache[key]!,
|
||||||
|
),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,10 +182,18 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
|||||||
BTBVTrustState state,
|
BTBVTrustState state,
|
||||||
) async {
|
) async {
|
||||||
await _lock.synchronized(() async {
|
await _lock.synchronized(() async {
|
||||||
trustCache[RatchetMapKey(jid, deviceId)] = state;
|
final key = RatchetMapKey(jid, deviceId);
|
||||||
|
trustCache[key] = state;
|
||||||
|
|
||||||
// Commit the state
|
// Commit the state
|
||||||
await commitState();
|
await commit(
|
||||||
|
BTBVTrustData(
|
||||||
|
jid,
|
||||||
|
deviceId,
|
||||||
|
state,
|
||||||
|
enablementCache[key]!,
|
||||||
|
),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,88 +209,39 @@ abstract class BlindTrustBeforeVerificationTrustManager extends TrustManager {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> setEnabled(String jid, int deviceId, bool enabled) async {
|
Future<void> setEnabled(String jid, int deviceId, bool enabled) async {
|
||||||
|
final key = RatchetMapKey(jid, deviceId);
|
||||||
await _lock.synchronized(() async {
|
await _lock.synchronized(() async {
|
||||||
enablementCache[RatchetMapKey(jid, deviceId)] = enabled;
|
enablementCache[key] = enabled;
|
||||||
});
|
|
||||||
|
|
||||||
// Commit the state
|
// Commit the state
|
||||||
await commitState();
|
await commit(
|
||||||
}
|
BTBVTrustData(
|
||||||
|
jid,
|
||||||
@override
|
deviceId,
|
||||||
Future<Map<String, dynamic>> toJson() async {
|
trustCache[key]!,
|
||||||
return {
|
enabled,
|
||||||
'devices': devices,
|
|
||||||
'trust': trustCache.map(
|
|
||||||
(key, value) => MapEntry(
|
|
||||||
key.toJsonKey(),
|
|
||||||
_trustToInt(value),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
'enable':
|
|
||||||
enablementCache.map((key, value) => MapEntry(key.toJsonKey(), value)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// From a serialized version of a BTBV trust manager, extract the device list.
|
|
||||||
/// NOTE: This is needed as Dart cannot just cast a List<dynamic> to List<int> and so on.
|
|
||||||
static Map<String, List<int>> deviceListFromJson(Map<String, dynamic> json) {
|
|
||||||
return (json['devices']! as Map<String, dynamic>).map<String, List<int>>(
|
|
||||||
(key, value) => MapEntry(
|
|
||||||
key,
|
|
||||||
(value as List<dynamic>).map<int>((i) => i as int).toList(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// From a serialized version of a BTBV trust manager, extract the trust cache.
|
|
||||||
/// NOTE: This is needed as Dart cannot just cast a List<dynamic> to List<int> and so on.
|
|
||||||
static Map<RatchetMapKey, BTBVTrustState> trustCacheFromJson(
|
|
||||||
Map<String, dynamic> json,
|
|
||||||
) {
|
|
||||||
return (json['trust']! as Map<String, dynamic>)
|
|
||||||
.map<RatchetMapKey, BTBVTrustState>(
|
|
||||||
(key, value) => MapEntry(
|
|
||||||
RatchetMapKey.fromJsonKey(key),
|
|
||||||
_trustFromInt(value as int),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// From a serialized version of a BTBV trust manager, extract the enable cache.
|
|
||||||
/// NOTE: This is needed as Dart cannot just cast a List<dynamic> to List<int> and so on.
|
|
||||||
static Map<RatchetMapKey, bool> enableCacheFromJson(
|
|
||||||
Map<String, dynamic> json,
|
|
||||||
) {
|
|
||||||
return (json['enable']! as Map<String, dynamic>).map<RatchetMapKey, bool>(
|
|
||||||
(key, value) => MapEntry(
|
|
||||||
RatchetMapKey.fromJsonKey(key),
|
|
||||||
value as bool,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> removeTrustDecisionsForJid(String jid) async {
|
Future<void> removeTrustDecisionsForJid(String jid) async {
|
||||||
await _lock.synchronized(() async {
|
await _lock.synchronized(() async {
|
||||||
|
// Clear the caches
|
||||||
|
for (final device in devices[jid]!) {
|
||||||
|
final key = RatchetMapKey(jid, device);
|
||||||
|
trustCache.remove(key);
|
||||||
|
enablementCache.remove(key);
|
||||||
|
}
|
||||||
devices.remove(jid);
|
devices.remove(jid);
|
||||||
await commitState();
|
|
||||||
|
// Commit the state
|
||||||
|
await removeTrust(jid);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the state of the trust manager has been changed. Allows the user to
|
|
||||||
/// commit the trust state to persistent storage.
|
|
||||||
@visibleForOverriding
|
|
||||||
Future<void> commitState();
|
|
||||||
|
|
||||||
@visibleForTesting
|
@visibleForTesting
|
||||||
BTBVTrustState getDeviceTrust(String jid, int deviceId) =>
|
BTBVTrustState getDeviceTrust(String jid, int deviceId) =>
|
||||||
trustCache[RatchetMapKey(jid, deviceId)]!;
|
trustCache[RatchetMapKey(jid, deviceId)]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A BTBV TrustManager that does not commit its state to persistent storage. Well suited
|
|
||||||
/// for testing.
|
|
||||||
class MemoryBTBVTrustManager extends BlindTrustBeforeVerificationTrustManager {
|
|
||||||
@override
|
|
||||||
Future<void> commitState() async {}
|
|
||||||
}
|
|
||||||
|
@ -20,7 +20,4 @@ class NeverTrustingTrustManager extends TrustManager {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> removeTrustDecisionsForJid(String jid) async {}
|
Future<void> removeTrustDecisionsForJid(String jid) async {}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Map<String, dynamic>> toJson() async => <String, dynamic>{};
|
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import 'package:test/test.dart';
|
|||||||
void main() {
|
void main() {
|
||||||
test('Test the Blind Trust Before Verification TrustManager', () async {
|
test('Test the Blind Trust Before Verification TrustManager', () async {
|
||||||
// Caroline's BTBV manager
|
// Caroline's BTBV manager
|
||||||
final btbv = MemoryBTBVTrustManager();
|
final btbv = BlindTrustBeforeVerificationTrustManager();
|
||||||
// Example data
|
// Example data
|
||||||
const aliceJid = 'alice@some.server';
|
const aliceJid = 'alice@some.server';
|
||||||
const bobJid = 'bob@other.server';
|
const bobJid = 'bob@other.server';
|
||||||
|
Loading…
Reference in New Issue
Block a user