using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Threading; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Renci.SshNet.Common; using Renci.SshNet.Tests.Common; namespace Renci.SshNet.Tests.Classes.Connection { [TestClass] public class Socks5ConnectorTest_Connect_UserNamePasswordAuthentication_UserNameExceedsMaximumLength : Socks5ConnectorTestBase { private ConnectionInfo _connectionInfo; private AsyncSocketListener _proxyServer; private Socket _clientSocket; private List _bytesReceivedByProxy; private bool _disconnected; private ProxyException _actualException; protected override void SetupData() { base.SetupData(); _connectionInfo = CreateConnectionInfo(new string('a', 256), new string('b', 255)); _connectionInfo.Timeout = TimeSpan.FromMilliseconds(100); _bytesReceivedByProxy = new List(); _actualException = null; _clientSocket = SocketFactory.Create(SocketType.Stream, ProtocolType.Tcp); _proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort)); _proxyServer.Disconnected += socket => _disconnected = true; _proxyServer.BytesReceived += (bytesReceived, socket) => { _bytesReceivedByProxy.AddRange(bytesReceived); // Wait until we received the greeting if (_bytesReceivedByProxy.Count == 4) { _ = socket.Send(new byte[] { // SOCKS version 0x05, // Username/password authentication 0x02 }); } }; _proxyServer.Start(); } protected override void SetupMocks() { _ = SocketFactoryMock.Setup(p => p.Create(SocketType.Stream, ProtocolType.Tcp)) .Returns(_clientSocket); } protected override void TearDown() { base.TearDown(); _proxyServer?.Dispose(); _clientSocket?.Dispose(); } protected override void Act() { try { _ = Connector.Connect(_connectionInfo); Assert.Fail(); } catch (ProxyException ex) { _actualException = ex; } // Give some time to process all messages Thread.Sleep(200); } [TestMethod] public void ConnectShouldHaveThrownProxyException() { Assert.IsNotNull(_actualException); Assert.IsNull(_actualException.InnerException); Assert.AreEqual("Proxy username is too long.", _actualException.Message); } [TestMethod] public void ProxyShouldHaveReceivedExpectedSocksRequest() { // Client greeting var expectedSocksRequest = new List { // SOCKS version 0x05, // Number of authentication methods supported 0x02, // No authentication 0x00, // Username/password 0x02 }; var errorText = string.Format("Expected:{0}{1}{0}but was:{0}{2}", Environment.NewLine, PacketDump.Create(expectedSocksRequest, 2), PacketDump.Create(_bytesReceivedByProxy, 2)); Assert.IsTrue(expectedSocksRequest.SequenceEqual(_bytesReceivedByProxy), errorText); } [TestMethod] public void ConnectionToProxyShouldHaveBeenShutDown() { Assert.IsTrue(_disconnected); } [TestMethod] public void ClientSocketShouldHaveBeenDisposed() { try { _ = _clientSocket.Receive(new byte[0]); Assert.Fail(); } catch (ObjectDisposedException) { } } [TestMethod] public void CreateOnSocketFactoryShouldHaveBeenInvokedOnce() { SocketFactoryMock.Verify(p => p.Create(SocketType.Stream, ProtocolType.Tcp), Times.Once()); } } }