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); } }
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); }