fix: A certificate rejection does not crash the connection

Fixes moxxy/moxxyv2#137.
This commit is contained in:
PapaTutuWawa 2022-11-12 20:56:44 +01:00
parent 848d83dc1f
commit 3172450b70
6 changed files with 100 additions and 5 deletions

View File

@ -12,3 +12,4 @@ analyzer:
- "**/*.g.dart"
- "**/*.freezed.dart"
- "test/"
- "integration_test/"

View File

@ -796,6 +796,15 @@ class XmppConnection {
_updateRoutingState(RoutingState.handleStanzas);
await _onNegotiationsDone();
} else if (_currentNegotiator!.state == NegotiatorState.error) {
_log.severe('Negotiator returned an error');
_updateRoutingState(RoutingState.error);
await _setConnectionState(XmppConnectionState.error);
_connectionCompleter?.complete(const XmppConnectionResult(false));
_connectionCompleter = null;
_closeSocket();
}
}

View File

@ -0,0 +1,64 @@
import 'package:logging/logging.dart';
import 'package:moxxmpp/moxxmpp.dart';
import 'package:moxxmpp_socket_tcp/moxxmpp_socket_tcp.dart';
import 'package:test/test.dart';
Future<void> _runTest(String domain) async {
var gotTLSException = false;
final socket = TCPSocketWrapper(false);
final log = Logger('TestLogger');
socket.getEventStream().listen((event) {
if (event is XmppSocketTLSFailedEvent) {
log.info('Got XmppSocketTLSFailedEvent from socket');
gotTLSException = true;
}
});
final connection = XmppConnection(
ExponentialBackoffReconnectionPolicy(),
socket,
);
connection.registerFeatureNegotiators([
StartTlsNegotiator(),
]);
connection.registerManagers([
DiscoManager(),
RosterManager(),
PingManager(),
MessageManager(),
PresenceManager('http://moxxmpp.example'),
]);
connection.setConnectionSettings(
ConnectionSettings(
jid: JID.fromString('testuser@$domain'),
password: 'abc123',
useDirectTLS: true,
allowPlainAuth: true,
),
);
final result = await connection.connectAwaitable();
expect(result.success, false);
expect(gotTLSException, true);
}
void main() {
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((record) {
print('${record.level.name}: ${record.time}: ${record.message}');
});
for (final domain in [
'self-signed.badxmpp.eu',
'expired.badxmpp.eu',
'wrong-name.badxmpp.eu',
'missing-chain.badxmpp.eu',
// TODO(Unknown): Technically, this one should not fail
//'ecdsa.badxmpp.eu',
]) {
test('$domain with connectAwaitable', () async {
await _runTest(domain);
});
}
}

View File

@ -1,4 +1,5 @@
library moxxmpp_socket_tcp;
export 'src/events.dart';
export 'src/record.dart';
export 'src/socket.dart';

View File

@ -0,0 +1,4 @@
import 'package:moxxmpp/moxxmpp.dart';
/// Triggered when TLS errors occur
class XmppSocketTLSFailedEvent extends XmppSocketEvent {}

View File

@ -4,6 +4,7 @@ import 'dart:io';
import 'package:logging/logging.dart';
import 'package:meta/meta.dart';
import 'package:moxxmpp/moxxmpp.dart';
import 'package:moxxmpp_socket_tcp/src/events.dart';
import 'package:moxxmpp_socket_tcp/src/record.dart';
import 'package:moxxmpp_socket_tcp/src/rfc_2782.dart';
@ -66,6 +67,7 @@ class TCPSocketWrapper extends BaseSocketWrapper {
return false;
}
var failedDueToTLS = false;
results.sort(srvRecordSortComparator);
for (final srv in results) {
try {
@ -91,12 +93,20 @@ class TCPSocketWrapper extends BaseSocketWrapper {
_secure = true;
_log.finest('Success!');
return true;
} on SocketException catch(e) {
} on Exception catch(e) {
_log.finest('Failure! $e');
_ignoreSocketClosure = false;
if (e is HandshakeException) {
failedDueToTLS = true;
}
}
}
if (failedDueToTLS) {
_eventStream.add(XmppSocketTLSFailedEvent());
}
return false;
}
@ -118,7 +128,7 @@ class TCPSocketWrapper extends BaseSocketWrapper {
_ignoreSocketClosure = false;
_log.finest('Success!');
return true;
} on SocketException catch(e) {
} on Exception catch(e) {
_log.finest('Failure! $e');
_ignoreSocketClosure = false;
continue;
@ -142,7 +152,7 @@ class TCPSocketWrapper extends BaseSocketWrapper {
);
_log.finest('Success!');
return true;
} on SocketException catch(e) {
} on Exception catch(e) {
_log.finest('Failure! $e');
_ignoreSocketClosure = false;
return false;
@ -183,8 +193,14 @@ class TCPSocketWrapper extends BaseSocketWrapper {
_ignoreSocketClosure = false;
_setupStreams();
return true;
} on SocketException {
} on Exception catch (e) {
_log.severe('Failed to secure socket: $e');
_ignoreSocketClosure = false;
if (e is HandshakeException) {
_eventStream.add(XmppSocketTLSFailedEvent());
}
return false;
}
}
@ -293,7 +309,7 @@ class TCPSocketWrapper extends BaseSocketWrapper {
try {
_socket!.write(data);
} on SocketException catch (e) {
} on Exception catch (e) {
_log.severe(e);
_eventStream.add(XmppSocketErrorEvent(e));
}