fix: Somewhat fix OMEMO

This commit is contained in:
PapaTutuWawa 2023-01-07 21:57:56 +01:00
parent 678564dbb3
commit d8de093e4d
5 changed files with 50 additions and 29 deletions

View File

@ -94,7 +94,7 @@ class XmppConnection {
_awaitingResponseLock = Lock(), _awaitingResponseLock = Lock(),
_xmppManagers = {}, _xmppManagers = {},
_incomingStanzaHandlers = List.empty(growable: true), _incomingStanzaHandlers = List.empty(growable: true),
_incomingEncryptionStanzaHandlers = List.empty(growable: true), _incomingPreStanzaHandlers = List.empty(growable: true),
_outgoingPreStanzaHandlers = List.empty(growable: true), _outgoingPreStanzaHandlers = List.empty(growable: true),
_outgoingPostStanzaHandlers = List.empty(growable: true), _outgoingPostStanzaHandlers = List.empty(growable: true),
_reconnectionPolicy = reconnectionPolicy, _reconnectionPolicy = reconnectionPolicy,
@ -134,7 +134,7 @@ class XmppConnection {
/// Helpers /// Helpers
/// ///
final List<StanzaHandler> _incomingStanzaHandlers; final List<StanzaHandler> _incomingStanzaHandlers;
final List<StanzaHandler> _incomingEncryptionStanzaHandlers; final List<StanzaHandler> _incomingPreStanzaHandlers;
final List<StanzaHandler> _outgoingPreStanzaHandlers; final List<StanzaHandler> _outgoingPreStanzaHandlers;
final List<StanzaHandler> _outgoingPostStanzaHandlers; final List<StanzaHandler> _outgoingPostStanzaHandlers;
final StreamController<XmppEvent> _eventStreamController; final StreamController<XmppEvent> _eventStreamController;
@ -225,13 +225,13 @@ class XmppConnection {
} }
_incomingStanzaHandlers.addAll(manager.getIncomingStanzaHandlers()); _incomingStanzaHandlers.addAll(manager.getIncomingStanzaHandlers());
_incomingEncryptionStanzaHandlers.addAll(manager.getIncomingEncryptionStanzaHandlers()); _incomingPreStanzaHandlers.addAll(manager.getIncomingPreStanzaHandlers());
_outgoingPreStanzaHandlers.addAll(manager.getOutgoingPreStanzaHandlers()); _outgoingPreStanzaHandlers.addAll(manager.getOutgoingPreStanzaHandlers());
_outgoingPostStanzaHandlers.addAll(manager.getOutgoingPostStanzaHandlers()); _outgoingPostStanzaHandlers.addAll(manager.getOutgoingPostStanzaHandlers());
if (sortHandlers) { if (sortHandlers) {
_incomingStanzaHandlers.sort(stanzaHandlerSortComparator); _incomingStanzaHandlers.sort(stanzaHandlerSortComparator);
_incomingEncryptionStanzaHandlers.sort(stanzaHandlerSortComparator); _incomingPreStanzaHandlers.sort(stanzaHandlerSortComparator);
_outgoingPreStanzaHandlers.sort(stanzaHandlerSortComparator); _outgoingPreStanzaHandlers.sort(stanzaHandlerSortComparator);
_outgoingPostStanzaHandlers.sort(stanzaHandlerSortComparator); _outgoingPostStanzaHandlers.sort(stanzaHandlerSortComparator);
} }
@ -634,12 +634,12 @@ class XmppConnection {
return state; return state;
} }
Future<StanzaHandlerData> _runIncomingStanzaHandlers(Stanza stanza) async { Future<StanzaHandlerData> _runIncomingStanzaHandlers(Stanza stanza, { StanzaHandlerData? initial }) async {
return _runStanzaHandlers(_incomingStanzaHandlers, stanza); return _runStanzaHandlers(_incomingStanzaHandlers, stanza, initial: initial);
} }
Future<StanzaHandlerData> _runIncomingEncryptionStanzaHandlers(Stanza stanza) async { Future<StanzaHandlerData> _runIncomingPreStanzaHandlers(Stanza stanza) async {
return _runStanzaHandlers(_incomingEncryptionStanzaHandlers, stanza); return _runStanzaHandlers(_incomingPreStanzaHandlers, stanza);
} }
Future<StanzaHandlerData> _runOutgoingPreStanzaHandlers(Stanza stanza, { StanzaHandlerData? initial }) async { Future<StanzaHandlerData> _runOutgoingPreStanzaHandlers(Stanza stanza, { StanzaHandlerData? initial }) async {
@ -681,18 +681,18 @@ class XmppConnection {
// Run the incoming stanza handlers and bounce with an error if no manager handled // Run the incoming stanza handlers and bounce with an error if no manager handled
// it. // it.
final incomingEncryptionHandlers = await _runIncomingEncryptionStanzaHandlers(stanza); final incomingPreHandlers = await _runIncomingPreStanzaHandlers(stanza);
final prefix = incomingEncryptionHandlers.encrypted ? final prefix = incomingPreHandlers.encrypted && incomingPreHandlers.other['encryption_error'] == null ?
'(Encrypted) ' : '(Encrypted) ' :
''; '';
_log.finest('<== $prefix${incomingEncryptionHandlers.stanza.toXml()}'); _log.finest('<== $prefix${incomingPreHandlers.stanza.toXml()}');
// See if we are waiting for this stanza // See if we are waiting for this stanza
final id = incomingEncryptionHandlers.stanza.attributes['id'] as String?; final id = incomingPreHandlers.stanza.attributes['id'] as String?;
var awaited = false; var awaited = false;
await _awaitingResponseLock.synchronized(() async { await _awaitingResponseLock.synchronized(() async {
if (id != null && _awaitingResponse.containsKey(id)) { if (id != null && _awaitingResponse.containsKey(id)) {
_awaitingResponse[id]!.complete(incomingEncryptionHandlers.stanza); _awaitingResponse[id]!.complete(incomingPreHandlers.stanza);
_awaitingResponse.remove(id); _awaitingResponse.remove(id);
awaited = true; awaited = true;
} }
@ -703,9 +703,18 @@ class XmppConnection {
} }
// Only bounce if the stanza has neither been awaited, nor handled. // Only bounce if the stanza has neither been awaited, nor handled.
final incomingHandlers = await _runIncomingStanzaHandlers(incomingEncryptionHandlers.stanza); final incomingHandlers = await _runIncomingStanzaHandlers(
incomingPreHandlers.stanza,
initial: StanzaHandlerData(
false,
incomingPreHandlers.cancel,
incomingPreHandlers.cancelReason,
incomingPreHandlers.stanza,
other: incomingPreHandlers.other,
),
);
if (!incomingHandlers.done) { if (!incomingHandlers.done) {
handleUnhandledStanza(this, stanza); handleUnhandledStanza(this, incomingPreHandlers.stanza);
} }
} }

View File

@ -32,9 +32,10 @@ abstract class XmppManagerBase {
/// receive. /// receive.
List<StanzaHandler> getIncomingStanzaHandlers() => []; List<StanzaHandler> getIncomingStanzaHandlers() => [];
/// Return the StanzaHandlers associated with this manager that deal with stanzas we /// Return the StanzaHandlers associated with this manager that deal with stanza handlers
/// may decrypt. /// that have to run before the main ones run. This is useful, for example, for OMEMO
List<StanzaHandler> getIncomingEncryptionStanzaHandlers() => []; /// as we have to decrypt the stanza before we do anything else.
List<StanzaHandler> getIncomingPreStanzaHandlers() => [];
/// Return the NonzaHandlers associated with this manager. /// Return the NonzaHandlers associated with this manager.
List<NonzaHandler> getNonzaHandlers() => []; List<NonzaHandler> getNonzaHandlers() => [];

View File

@ -25,13 +25,12 @@ class CarbonsManager extends XmppManagerBase {
String getName() => 'CarbonsManager'; String getName() => 'CarbonsManager';
@override @override
List<StanzaHandler> getIncomingStanzaHandlers() => [ List<StanzaHandler> getIncomingPreStanzaHandlers() => [
StanzaHandler( StanzaHandler(
stanzaTag: 'message', stanzaTag: 'message',
tagName: 'received', tagName: 'received',
tagXmlns: carbonsXmlns, tagXmlns: carbonsXmlns,
callback: _onMessageReceived, callback: _onMessageReceived,
// Before all managers the message manager depends on
priority: -98, priority: -98,
), ),
StanzaHandler( StanzaHandler(
@ -39,7 +38,6 @@ class CarbonsManager extends XmppManagerBase {
tagName: 'sent', tagName: 'sent',
tagXmlns: carbonsXmlns, tagXmlns: carbonsXmlns,
callback: _onMessageSent, callback: _onMessageSent,
// Before all managers the message manager depends on
priority: -98, priority: -98,
) )
]; ];

View File

@ -7,3 +7,5 @@ class InvalidAffixElementsException with Exception {}
class OmemoNotSupportedForContactException extends OmemoError {} class OmemoNotSupportedForContactException extends OmemoError {}
class EncryptionFailedException with Exception {} class EncryptionFailedException with Exception {}
class InvalidEnvelopePayloadException with Exception {}

View File

@ -24,6 +24,7 @@ import 'package:moxxmpp/src/xeps/xep_0384/errors.dart';
import 'package:moxxmpp/src/xeps/xep_0384/helpers.dart'; import 'package:moxxmpp/src/xeps/xep_0384/helpers.dart';
import 'package:moxxmpp/src/xeps/xep_0384/types.dart'; import 'package:moxxmpp/src/xeps/xep_0384/types.dart';
import 'package:omemo_dart/omemo_dart.dart'; import 'package:omemo_dart/omemo_dart.dart';
import 'package:xml/xml.dart';
const _doNotEncryptList = [ const _doNotEncryptList = [
// XEP-0033 // XEP-0033
@ -53,27 +54,24 @@ abstract class BaseOmemoManager extends XmppManagerBase {
Future<bool> isSupported() async => true; Future<bool> isSupported() async => true;
@override @override
List<StanzaHandler> getIncomingEncryptionStanzaHandlers() => [ List<StanzaHandler> getIncomingPreStanzaHandlers() => [
StanzaHandler( StanzaHandler(
stanzaTag: 'iq', stanzaTag: 'iq',
tagXmlns: omemoXmlns, tagXmlns: omemoXmlns,
tagName: 'encrypted', tagName: 'encrypted',
callback: _onIncomingStanza, callback: _onIncomingStanza,
priority: 9999,
), ),
StanzaHandler( StanzaHandler(
stanzaTag: 'presence', stanzaTag: 'presence',
tagXmlns: omemoXmlns, tagXmlns: omemoXmlns,
tagName: 'encrypted', tagName: 'encrypted',
callback: _onIncomingStanza, callback: _onIncomingStanza,
priority: 9999,
), ),
StanzaHandler( StanzaHandler(
stanzaTag: 'message', stanzaTag: 'message',
tagXmlns: omemoXmlns, tagXmlns: omemoXmlns,
tagName: 'encrypted', tagName: 'encrypted',
callback: _onIncomingStanza, callback: _onIncomingStanza,
priority: -98,
), ),
]; ];
@ -432,16 +430,29 @@ abstract class BaseOmemoManager extends XmppManagerBase {
), ),
); );
final children = stanza.children.where(
(child) => child.tag != 'encrypted' || child.attributes['xmlns'] != omemoXmlns,
).toList();
final other = Map<String, dynamic>.from(state.other); final other = Map<String, dynamic>.from(state.other);
var children = stanza.children;
if (result.error != null) { if (result.error != null) {
other['encryption_error'] = result.error; other['encryption_error'] = result.error;
} else {
children = stanza.children.where(
(child) => child.tag != 'encrypted' || child.attributes['xmlns'] != omemoXmlns,
).toList();
} }
if (result.payload != null) { if (result.payload != null) {
final envelope = XMLNode.fromString(result.payload!); XMLNode envelope;
try {
envelope = XMLNode.fromString(result.payload!);
} on XmlParserException catch (_) {
logger.warning('Failed to parse envelope payload: ${result.payload!}');
other['encryption_error'] = InvalidEnvelopePayloadException();
return state.copyWith(
encrypted: true,
other: other,
);
}
children.addAll( children.addAll(
envelope.firstTag('content')!.children, envelope.firstTag('content')!.children,
); );