public void SocketShouldBeClosedAndBindShouldEndWhenOnErrorOccurredIsInvoked()
        {
            _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 signalSessionErrorOccurredThread =
                        new Thread(() =>
                    {
                        // sleep for a short period to allow channel to actually start receiving from socket
                        Thread.Sleep(100);
                        // raise ErrorOccured event on session
                        _sessionMock.Raise(s => s.ErrorOccured += null,
                                           new ExceptionEventArgs(new SystemException()));
                    });
                    signalSessionErrorOccurredThread.Start();

                    channel.Bind();

                    signalSessionErrorOccurredThread.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);
            }
        }
예제 #3
0
        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);
            _connectionInfoMock = new Mock <IConnectionInfo>(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);
        }
예제 #4
0
        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(-1));
            _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);
            }
        }
예제 #5
0
        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     = null;
                byte[]    addressBuffer = null;
                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 Renci.SshNet.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);
            }
        }