Implements "direct-tcpip" SSH channel.
Наследование: ClientChannel, IChannelDirectTcpip
        public void SocketShouldBeClosedAndBindShouldEndWhenForwardedPortSignalsClosingEvent()
        {
            _sessionMock.Setup(p => p.IsConnected).Returns(true);
            _sessionMock.Setup(p => p.SendMessage(It.IsAny<ChannelOpenMessage>()))
                .Callback<Message>(m => _sessionMock.Raise(p => p.ChannelOpenConfirmationReceived += null,
                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
                        new ChannelOpenConfirmationMessage(((ChannelOpenMessage)m).LocalChannelNumber, _remoteWindowSize, _remotePacketSize, _remoteChannelNumber))));
            _sessionMock.Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
                .Callback<WaitHandle>(p => p.WaitOne(Session.Infinite));

            var localPortEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
            using (var localPortListener = new AsyncSocketListener(localPortEndPoint))
            {
                localPortListener.Start();

                localPortListener.Connected += socket =>
                    {
                        var channel = new ChannelDirectTcpip(_sessionMock.Object, _localChannelNumber, _localWindowSize,
                            _localPacketSize);
                        channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);

                        var closeForwardedPortThread =
                            new Thread(() =>
                                {
                                    // sleep for a short period to allow channel to actually start receiving from socket
                                    Thread.Sleep(100);
                                    // raise Closing event on forwarded port
                                    _forwardedPortMock.Raise(p => p.Closing += null, EventArgs.Empty);
                                });
                        closeForwardedPortThread.Start();

                        channel.Bind();

                        closeForwardedPortThread.Join();
                    };

                var client = new Socket(localPortEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                client.Connect(localPortEndPoint);

                // attempt to receive from socket to verify it was shut down by channel
                var buffer = new byte[16];
                var bytesReceived = client.Receive(buffer, 0, buffer.Length, SocketFlags.None);
                Assert.AreEqual(0, bytesReceived);
                Assert.IsTrue(client.Connected);
                // signal to server that we also shut down the socket at our end
                client.Shutdown(SocketShutdown.Send);
            }
        }
Пример #2
0
        private void HandleSocks4(Socket socket, ChannelDirectTcpip channel)
        {
            using (var stream = new NetworkStream(socket))
            {
                var commandCode = stream.ReadByte();
                //  TODO:   See what need to be done depends on the code

                var portBuffer = new byte[2];
                stream.Read(portBuffer, 0, portBuffer.Length);
                var port = (uint)(portBuffer[0] * 256 + portBuffer[1]);

                var ipBuffer = new byte[4];
                stream.Read(ipBuffer, 0, ipBuffer.Length);
                var ipAddress = new IPAddress(ipBuffer);

                var username = ReadString(stream);

                var host = ipAddress.ToString();

                this.RaiseRequestReceived(host, port);

                channel.Open(host, port, socket);

                stream.WriteByte(0x00);

                if (channel.IsOpen)
                {
                    stream.WriteByte(0x5a);
                }
                else
                {
                    stream.WriteByte(0x5b);
                }

                stream.Write(portBuffer, 0, portBuffer.Length);
                stream.Write(ipBuffer, 0, ipBuffer.Length);
            }
        }
        public void SocketShouldBeClosedAndEofShouldBeSentToServerWhenClientShutsDownSocket()
        {
            _sessionMock.Setup(p => p.IsConnected).Returns(true);
            _sessionMock.Setup(p => p.SendMessage(It.IsAny<ChannelOpenMessage>()))
                .Callback<Message>(m => _sessionMock.Raise(p => p.ChannelOpenConfirmationReceived += null,
                    new MessageEventArgs<ChannelOpenConfirmationMessage>(
                        new ChannelOpenConfirmationMessage(((ChannelOpenMessage) m).LocalChannelNumber,
                            _remoteWindowSize, _remotePacketSize, _remoteChannelNumber))));
            _sessionMock.Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
                .Callback<WaitHandle>(p => p.WaitOne(Session.Infinite));
            _sessionMock.Setup(p => p.ConnectionInfo).Returns(_connectionInfoMock.Object);
            _connectionInfoMock.Setup(p => p.Timeout).Returns(TimeSpan.FromSeconds(60));
            _sessionMock.Setup(p => p.TrySendMessage(It.IsAny<ChannelEofMessage>()))
                .Returns(true)
                .Callback<Message>(
                    m => new Thread(() =>
                        {
                            Thread.Sleep(50);
                            _sessionMock.Raise(s => s.ChannelEofReceived += null,
                                new MessageEventArgs<ChannelEofMessage>(new ChannelEofMessage(_localChannelNumber)));
                        }).Start());
            _sessionMock.Setup(p => p.TrySendMessage(It.IsAny<ChannelCloseMessage>()))
                .Returns(true)
                .Callback<Message>(
                    m => new Thread(() =>
                        {
                            Thread.Sleep(50);
                            _sessionMock.Raise(s => s.ChannelCloseReceived += null,
                                new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
                        }).Start());
            var channelBindFinishedWaitHandle = new ManualResetEvent(false);
            Socket handler = null;
            ChannelDirectTcpip channel = null;

            var localPortEndPoint = new IPEndPoint(IPAddress.Loopback, 8122);
            using (var localPortListener = new AsyncSocketListener(localPortEndPoint))
            {
                localPortListener.Start();

                localPortListener.Connected += socket =>
                    {
                        channel = new ChannelDirectTcpip(_sessionMock.Object, _localChannelNumber, _localWindowSize,
                            _localPacketSize);
                        channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
                        channel.Bind();
                        channel.Close();

                        handler = socket;

                        channelBindFinishedWaitHandle.Set();
                    };

                var client = new Socket(localPortEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                client.Connect(localPortEndPoint);
                client.Shutdown(SocketShutdown.Send);
                Assert.IsFalse(client.Connected);

                channelBindFinishedWaitHandle.WaitOne();

                Assert.IsNotNull(handler);
                Assert.IsFalse(handler.Connected);

                _sessionMock.Verify(p => p.TrySendMessage(It.IsAny<ChannelEofMessage>()), Times.Once);
                _sessionMock.Verify(p => p.TrySendMessage(It.IsAny<ChannelCloseMessage>()), Times.Once);

                channel.Close();

                _sessionMock.Verify(p => p.TrySendMessage(It.IsAny<ChannelEofMessage>()), Times.Once);
                _sessionMock.Verify(p => p.TrySendMessage(It.IsAny<ChannelCloseMessage>()), Times.Once);
            }
        }
        private void HandleSocks5(Socket socket, ChannelDirectTcpip channel)
        {
            using (var stream = new NetworkStream(socket))
            {
                var authenticationMethodsCount = stream.ReadByte();

                var authenticationMethods = new byte[authenticationMethodsCount];
                stream.Read(authenticationMethods, 0, authenticationMethods.Length);

                stream.WriteByte(0x05);

                if (authenticationMethods.Min() == 0)
                {
                    stream.WriteByte(0x00);
                }
                else
                {
                    stream.WriteByte(0xFF);
                }

                var version = stream.ReadByte();

                if (version != 5)
                    throw new ProxyException("SOCKS5: Version 5 is expected.");

                var commandCode = stream.ReadByte();

                if (stream.ReadByte() != 0)
                {
                    throw new ProxyException("SOCKS5: 0 is expected.");
                }

                var addressType = stream.ReadByte();

                IPAddress ipAddress;
                byte[] addressBuffer;
                switch (addressType)
                {
                    case 0x01:
                        {
                            addressBuffer = new byte[4];
                            stream.Read(addressBuffer, 0, 4);

                            ipAddress = new IPAddress(addressBuffer);
                        }
                        break;
                    case 0x03:
                        {
                            var length = stream.ReadByte();
                            addressBuffer = new byte[length];
                            stream.Read(addressBuffer, 0, addressBuffer.Length);

                            ipAddress = IPAddress.Parse(new Common.ASCIIEncoding().GetString(addressBuffer));
                        }
                        break;
                    case 0x04:
                        {
                            addressBuffer = new byte[16];
                            stream.Read(addressBuffer, 0, 16);

                            ipAddress = new IPAddress(addressBuffer);
                        }
                        break;
                    default:
                        throw new ProxyException(string.Format("SOCKS5: Address type '{0}' is not supported.", addressType));
                }

                var portBuffer = new byte[2];
                stream.Read(portBuffer, 0, portBuffer.Length);
                var port = (uint)(portBuffer[0] * 256 + portBuffer[1]);
                var host = ipAddress.ToString();

                this.RaiseRequestReceived(host, port);

                channel.Open(host, port, socket);

                stream.WriteByte(0x05);

                if (channel.IsOpen)
                {
                    stream.WriteByte(0x00);
                }
                else
                {
                    stream.WriteByte(0x01);
                }

                stream.WriteByte(0x00);

                var buffer = ipAddress.GetAddressBytes();

                if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
                {
                    stream.WriteByte(0x01);
                }
                else if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
                {
                    stream.WriteByte(0x04);
                }
                else
                {
                    throw new NotSupportedException("Not supported address family.");
                }

                stream.Write(buffer, 0, buffer.Length);
                stream.Write(portBuffer, 0, portBuffer.Length);
            }
        }
        private void Arrange()
        {
            var random = new Random();
            _localChannelNumber = (uint) random.Next(0, int.MaxValue);
            _localWindowSize = (uint) random.Next(2000, 3000);
            _localPacketSize = (uint) random.Next(1000, 2000);
            _remoteHost = random.Next().ToString(CultureInfo.InvariantCulture);
            _port = (uint) random.Next(IPEndPoint.MinPort, IPEndPoint.MaxPort);
            _channelBindFinishedWaitHandle = new ManualResetEvent(false);
            _clientReceivedFinishedWaitHandle = new ManualResetEvent(false);
            _channelException = null;

            _remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
            _remoteWindowSize = (uint)random.Next(0, int.MaxValue);
            _remotePacketSize = (uint)random.Next(100, 200);

            _sessionMock = new Mock<ISession>(MockBehavior.Strict);
            _forwardedPortMock = new Mock<IForwardedPort>(MockBehavior.Strict);

            var sequence = new MockSequence();
            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
            _sessionMock.InSequence(sequence)
                .Setup(p => p.SendMessage(It.Is<ChannelOpenMessage>(m => AssertExpectedMessage(m))));
            _sessionMock.InSequence(sequence)
                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
                .Callback<WaitHandle>(
                    w =>
                    {
                        _sessionMock.Raise(
                            s => s.ChannelOpenConfirmationReceived += null,
                            new MessageEventArgs<ChannelOpenConfirmationMessage>(
                                new ChannelOpenConfirmationMessage(
                                    _localChannelNumber,
                                    _remoteWindowSize,
                                    _remotePacketSize,
                                    _remoteChannelNumber)));
                        w.WaitOne();
                    });
            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
            _sessionMock.InSequence(sequence)
                .Setup(
                    p => p.TrySendMessage(It.Is<ChannelEofMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
                .Returns(true);
            _sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
            _sessionMock.InSequence(sequence)
                .Setup(
                    p => p.TrySendMessage(It.Is<ChannelCloseMessage>(m => m.LocalChannelNumber == _remoteChannelNumber)))
                .Returns(true);
            _sessionMock.InSequence(sequence)
                .Setup(p => p.WaitOnHandle(It.IsNotNull<WaitHandle>()))
                .Callback<WaitHandle>(
                    w =>
                    {
                        _sessionMock.Raise(
                            s => s.ChannelCloseReceived += null,
                            new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
                        w.WaitOne();
                    });

            var localEndpoint = new IPEndPoint(IPAddress.Loopback, 8122);
            _listener = new AsyncSocketListener(localEndpoint);
            _listener.Connected += socket =>
                {
                    try
                    {
                        _channel = new ChannelDirectTcpip(
                            _sessionMock.Object,
                            _localChannelNumber,
                            _localWindowSize,
                            _localPacketSize);
                        _channel.Open(_remoteHost, _port, _forwardedPortMock.Object, socket);
                        _channel.Bind();
                    }
                    catch (Exception ex)
                    {
                        _channelException = ex;
                    }
                    finally
                    {
                        _channelBindFinishedWaitHandle.Set();
                    }
                };
            _listener.Start();

            _client = new Socket(localEndpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            _client.Connect(localEndpoint);

            var clientReceiveThread = new Thread(
                () =>
                    {
                        var buffer = new byte[16];
                        var bytesReceived = _client.Receive(buffer, 0, buffer.Length, SocketFlags.None);
                        if (bytesReceived == 0)
                        {
                            _client.Shutdown(SocketShutdown.Send);
                            _clientReceivedFinishedWaitHandle.Set();
                        }
                    }
                );
            clientReceiveThread.Start();

            // give channel time to bind to socket
            Thread.Sleep(200);
        }