From 69eaf7b5eb489924f164b0b2bce6bdf6a4ebfc16 Mon Sep 17 00:00:00 2001 From: Alan McGovern Date: Thu, 15 Aug 2019 16:31:07 +0100 Subject: [PATCH] [core] Ensure EncryptorFactory actually receives the data we requested If the initial buffer is unencrypted we can return it straight away if plain text connections are supported. If the initial buffer is encrypted, then it will be consumed as part of the normal encrypted connection negotiation, so we'll need to receive the actual data before returning. --- .../EncryptorFactory.cs | 11 +++++++++-- .../Managers/ListenManager.cs | 18 ++---------------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/MonoTorrent/MonoTorrent.Client.Encryption/EncryptorFactory.cs b/src/MonoTorrent/MonoTorrent.Client.Encryption/EncryptorFactory.cs index 7035402b6..f647959fe 100644 --- a/src/MonoTorrent/MonoTorrent.Client.Encryption/EncryptorFactory.cs +++ b/src/MonoTorrent/MonoTorrent.Client.Encryption/EncryptorFactory.cs @@ -82,9 +82,8 @@ static async Task DoCheckIncomingConnectionAsync(IConnection co message.Decode(buffer, 0, buffer.Length); if (message.ProtocolString == VersionInfo.ProtocolStringV100) { - if (supportsPlainText) { + if (supportsPlainText) return new EncryptorResult (PlainTextEncryption.Instance, PlainTextEncryption.Instance, buffer); - } } else if (supportsRC4Header || supportsRC4Full) { @@ -96,7 +95,15 @@ static async Task DoCheckIncomingConnectionAsync(IConnection co if (encSocket.Decryptor is RC4 && !supportsRC4Full) throw new EncryptionException("Decryptor was RC4Full but that is not allowed"); + // As the connection was encrypted, the data we got from the initial Receive call will have + // been consumed during the crypto handshake process. Now that the encrypted handshake has + // been established, we should ensure we read the data again. var data = encSocket.InitialData?.Length > 0 ? encSocket.InitialData : null; + if (data == null && bytesToReceive > 0) { + data = buffer; + await NetworkIO.ReceiveAsync (connection, data, 0, data.Length, null, null, null); + encSocket.Decryptor.Decrypt (data); + } return new EncryptorResult (encSocket.Decryptor, encSocket.Encryptor, data); } diff --git a/src/MonoTorrent/MonoTorrent.Client/Managers/ListenManager.cs b/src/MonoTorrent/MonoTorrent.Client/Managers/ListenManager.cs index f6aa6f39f..25500159b 100644 --- a/src/MonoTorrent/MonoTorrent.Client/Managers/ListenManager.cs +++ b/src/MonoTorrent/MonoTorrent.Client/Managers/ListenManager.cs @@ -109,23 +109,9 @@ private async void ConnectionReceived(object sender, NewConnectionEventArgs e) var result = await EncryptorFactory.CheckIncomingConnectionAsync(id.Connection, id.Peer.Encryption, Engine.Settings, HandshakeMessage.HandshakeLength, skeys.ToArray()); id.Decryptor = result.Decryptor; id.Encryptor = result.Encryptor; - var initialData = result.InitialData; - if (initialData != null && initialData.Length != HandshakeMessage.HandshakeLength) - { - e.Connection.Dispose(); - return; - } - HandshakeMessage handshake; - if (initialData == null) - { - handshake = await PeerIO.ReceiveHandshakeAsync(id.Connection, id.Decryptor); - } - else - { - handshake = new HandshakeMessage(); - handshake.Decode(initialData, 0, initialData.Length); - } + var handshake = new HandshakeMessage(); + handshake.Decode(result.InitialData, 0, result.InitialData.Length); if (!await HandleHandshake(id, handshake)) e.Connection.Dispose(); }