Skip to content

Commit d972a5e

Browse files
committed
ENH: Implement SSH Jump as ProxyConnection
Rewrite some interfaces to allow this new type of ProxyConnection Additionally, store and use information on proxy connections as a IConnectionInfo object "ProxyConnection" in the IConnectionInfo object. This allows the user to specify multiple proxies to connect through before making the final connection to the target (which will be done using a "DirectConnector" instance). Update tests to reflect new interface
1 parent 865edf2 commit d972a5e

File tree

116 files changed

+984
-370
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+984
-370
lines changed

src/Renci.SshNet.Tests/Classes/Channels/ChannelDirectTcpipTest.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class ChannelDirectTcpipTestTest : TestBase
1818
{
1919
private Mock<ISession> _sessionMock;
2020
private Mock<IForwardedPort> _forwardedPortMock;
21-
private Mock<IConnectionInfo> _connectionInfoMock;
21+
private Mock<ISshConnectionInfo> _connectionInfoMock;
2222
private uint _localChannelNumber;
2323
private uint _localWindowSize;
2424
private uint _localPacketSize;
@@ -47,7 +47,7 @@ protected override void OnInit()
4747

4848
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
4949
_forwardedPortMock = new Mock<IForwardedPort>(MockBehavior.Strict);
50-
_connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
50+
_connectionInfoMock = new Mock<ISshConnectionInfo>(MockBehavior.Strict);
5151
}
5252

5353
[TestMethod]

src/Renci.SshNet.Tests/Classes/Channels/ChannelDirectTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
1818
public class ChannelDirectTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen
1919
{
2020
private Mock<ISession> _sessionMock;
21-
private Mock<IConnectionInfo> _connectionInfoMock;
21+
private Mock<ISshConnectionInfo> _connectionInfoMock;
2222
private Mock<IForwardedPort> _forwardedPortMock;
2323
private ChannelDirectTcpip _channel;
2424
private uint _localChannelNumber;
@@ -78,7 +78,7 @@ private void Arrange()
7878
_remotePacketSize = (uint)random.Next(100, 200);
7979

8080
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
81-
_connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
81+
_connectionInfoMock = new Mock<ISshConnectionInfo>(MockBehavior.Strict);
8282
_forwardedPortMock = new Mock<IForwardedPort>(MockBehavior.Strict);
8383

8484
var sequence = new MockSequence();

src/Renci.SshNet.Tests/Classes/Channels/ChannelForwardedTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpen.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class ChannelForwardedTcpipTest_Dispose_SessionIsConnectedAndChannelIsOpe
1717
{
1818
private Mock<ISession> _sessionMock;
1919
private Mock<IForwardedPort> _forwardedPortMock;
20-
private Mock<IConnectionInfo> _connectionInfoMock;
20+
private Mock<ISshConnectionInfo> _connectionInfoMock;
2121
private ChannelForwardedTcpip _channel;
2222
private uint _localChannelNumber;
2323
private uint _localWindowSize;
@@ -83,7 +83,7 @@ private void Arrange()
8383
_remoteEndpoint = new IPEndPoint(IPAddress.Loopback, 8122);
8484

8585
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
86-
_connectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
86+
_connectionInfoMock = new Mock<ISshConnectionInfo>(MockBehavior.Strict);
8787
_forwardedPortMock = new Mock<IForwardedPort>(MockBehavior.Strict);
8888

8989
var sequence = new MockSequence();

src/Renci.SshNet.Tests/Classes/Channels/ChannelSessionTestBase.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
66
public abstract class ChannelSessionTestBase
77
{
88
internal Mock<ISession> SessionMock { get; private set; }
9-
internal Mock<IConnectionInfo> ConnectionInfoMock { get; private set; }
9+
internal Mock<ISshConnectionInfo> ConnectionInfoMock { get; private set; }
1010

1111
[TestInitialize]
1212
public void Initialize()
@@ -20,7 +20,7 @@ public void Initialize()
2020
protected void CreateMocks()
2121
{
2222
SessionMock = new Mock<ISession>(MockBehavior.Strict);
23-
ConnectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
23+
ConnectionInfoMock = new Mock<ISshConnectionInfo>(MockBehavior.Strict);
2424
}
2525

2626
protected abstract void SetupMocks();

src/Renci.SshNet.Tests/Classes/Channels/ChannelTestBase.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace Renci.SshNet.Tests.Classes.Channels
66
public abstract class ChannelTestBase
77
{
88
internal Mock<ISession> SessionMock { get; private set; }
9-
internal Mock<IConnectionInfo> ConnectionInfoMock { get; private set; }
9+
internal Mock<ISshConnectionInfo> ConnectionInfoMock { get; private set; }
1010

1111
[TestInitialize]
1212
public void Initialize()
@@ -20,7 +20,7 @@ public void Initialize()
2020
protected void CreateMocks()
2121
{
2222
SessionMock = new Mock<ISession>(MockBehavior.Strict);
23-
ConnectionInfoMock = new Mock<IConnectionInfo>(MockBehavior.Strict);
23+
ConnectionInfoMock = new Mock<ISshConnectionInfo>(MockBehavior.Strict);
2424
}
2525

2626
protected abstract void SetupMocks();

src/Renci.SshNet.Tests/Classes/Connection/DirectConnectorTestBase.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,21 @@ namespace Renci.SshNet.Tests.Classes.Connection
77
{
88
public abstract class DirectConnectorTestBase : TripleATestBase
99
{
10+
internal Mock<IServiceFactory> ServiceFactoryMock { get; private set; }
11+
1012
internal Mock<ISocketFactory> SocketFactoryMock { get; private set; }
1113
internal DirectConnector Connector { get; private set; }
1214
internal SocketFactory SocketFactory { get; private set; }
1315

1416
protected virtual void CreateMocks()
1517
{
18+
ServiceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
1619
SocketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
1720
}
1821

1922
protected virtual void SetupData()
2023
{
21-
Connector = new DirectConnector(SocketFactoryMock.Object);
24+
Connector = new DirectConnector(ServiceFactoryMock.Object, SocketFactoryMock.Object);
2225
SocketFactory = new SocketFactory();
2326
}
2427

src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTestBase.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,22 @@ namespace Renci.SshNet.Tests.Classes.Connection
66
{
77
public abstract class HttpConnectorTestBase : TripleATestBase
88
{
9+
internal Mock<IServiceFactory> ServiceFactoryMock { get; private set; }
910
internal Mock<ISocketFactory> SocketFactoryMock { get; private set; }
1011
internal HttpConnector Connector { get; private set; }
1112
internal SocketFactory SocketFactory { get; private set; }
13+
internal ServiceFactory ServiceFactory { get; private set; }
1214

1315
protected virtual void CreateMocks()
1416
{
17+
ServiceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
1518
SocketFactoryMock = new Mock<ISocketFactory>(MockBehavior.Strict);
1619
}
1720

1821
protected virtual void SetupData()
1922
{
20-
Connector = new HttpConnector(SocketFactoryMock.Object);
23+
Connector = new HttpConnector(ServiceFactoryMock.Object, SocketFactoryMock.Object);
24+
ServiceFactory = new ServiceFactory();
2125
SocketFactory = new SocketFactory();
2226
}
2327

src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ConnectionToProxyRefused.cs

+12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.VisualStudio.TestTools.UnitTesting;
22
using Moq;
3+
using Renci.SshNet.Connection;
34
using Renci.SshNet.Common;
45
using System;
56
using System.Diagnostics;
@@ -12,8 +13,10 @@ namespace Renci.SshNet.Tests.Classes.Connection
1213
public class HttpConnectorTest_Connect_ConnectionToProxyRefused : HttpConnectorTestBase
1314
{
1415
private ConnectionInfo _connectionInfo;
16+
private ProxyConnectionInfo _proxyConnectionInfo;
1517
private SocketException _actualException;
1618
private Socket _clientSocket;
19+
private IConnector _proxyConnector;
1720
private Stopwatch _stopWatch;
1821

1922
protected override void SetupData()
@@ -30,16 +33,20 @@ protected override void SetupData()
3033
"proxyPwd",
3134
new KeyboardInteractiveAuthenticationMethod("user"));
3235
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(5000);
36+
_proxyConnectionInfo = (ProxyConnectionInfo)_connectionInfo.ProxyConnection;
3337
_stopWatch = new Stopwatch();
3438
_actualException = null;
3539

3640
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
41+
_proxyConnector = ServiceFactory.CreateConnector(_proxyConnectionInfo, SocketFactory);
3742
}
3843

3944
protected override void SetupMocks()
4045
{
4146
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
4247
.Returns(_clientSocket);
48+
ServiceFactoryMock.Setup(p => p.CreateConnector(_proxyConnectionInfo, SocketFactory))
49+
.Returns(_proxyConnector);
4350
}
4451

4552
protected override void TearDown()
@@ -50,6 +57,11 @@ protected override void TearDown()
5057
{
5158
_clientSocket.Dispose();
5259
}
60+
61+
if (_proxyConnector != null)
62+
{
63+
_proxyConnector.Dispose();
64+
}
5365
}
5466

5567
protected override void Act()

src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyClosesConnectionBeforeStatusLineIsSent.cs

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.VisualStudio.TestTools.UnitTesting;
22
using Moq;
3+
using Renci.SshNet.Connection;
34
using Renci.SshNet.Common;
45
using Renci.SshNet.Tests.Common;
56
using System;
@@ -12,8 +13,10 @@ namespace Renci.SshNet.Tests.Classes.Connection
1213
public class HttpConnectorTest_Connect_ProxyClosesConnectionBeforeStatusLineIsSent : HttpConnectorTestBase
1314
{
1415
private ConnectionInfo _connectionInfo;
16+
private ProxyConnectionInfo _proxyConnectionInfo;
1517
private AsyncSocketListener _proxyServer;
1618
private Socket _clientSocket;
19+
private IConnector _proxyConnector;
1720
private bool _disconnected;
1821
private ProxyException _actualException;
1922

@@ -30,12 +33,14 @@ protected override void SetupData()
3033
"proxyUser",
3134
"proxyPwd",
3235
new KeyboardInteractiveAuthenticationMethod("user"));
36+
_proxyConnectionInfo = (ProxyConnectionInfo)_connectionInfo.ProxyConnection;
3337
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(100);
3438
_actualException = null;
3539

3640
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
41+
_proxyConnector = ServiceFactory.CreateConnector(_proxyConnectionInfo, SocketFactory);
3742

38-
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
43+
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _proxyConnectionInfo.Port));
3944
_proxyServer.Disconnected += socket => _disconnected = true;
4045
_proxyServer.BytesReceived += (bytesReceived, socket) =>
4146
{
@@ -48,6 +53,8 @@ protected override void SetupMocks()
4853
{
4954
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
5055
.Returns(_clientSocket);
56+
ServiceFactoryMock.Setup(p => p.CreateConnector(_proxyConnectionInfo, SocketFactory))
57+
.Returns(_proxyConnector);
5158
}
5259

5360
protected override void TearDown()
@@ -63,6 +70,11 @@ protected override void TearDown()
6370
{
6471
_clientSocket.Dispose();
6572
}
73+
74+
if (_proxyConnector != null)
75+
{
76+
_proxyConnector.Dispose();
77+
}
6678
}
6779

6880
protected override void Act()

src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyHostInvalid.cs

+21
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
using Renci.SshNet.Connection;
23
using System.Net.Sockets;
34

45
namespace Renci.SshNet.Tests.Classes.Connection
@@ -7,6 +8,8 @@ namespace Renci.SshNet.Tests.Classes.Connection
78
public class HttpConnectorTest_Connect_ProxyHostInvalid : HttpConnectorTestBase
89
{
910
private ConnectionInfo _connectionInfo;
11+
private ProxyConnectionInfo _proxyConnectionInfo;
12+
private IConnector _proxyConnector;
1013
private SocketException _actualException;
1114

1215
protected override void SetupData()
@@ -22,9 +25,27 @@ protected override void SetupData()
2225
"proxyUser",
2326
"proxyPwd",
2427
new KeyboardInteractiveAuthenticationMethod("user"));
28+
_proxyConnectionInfo = (ProxyConnectionInfo)_connectionInfo.ProxyConnection;
29+
_proxyConnector = ServiceFactory.CreateConnector(_proxyConnectionInfo, SocketFactory);
2530
_actualException = null;
2631
}
2732

33+
protected override void SetupMocks()
34+
{
35+
ServiceFactoryMock.Setup(p => p.CreateConnector(_proxyConnectionInfo, SocketFactory))
36+
.Returns(_proxyConnector);
37+
}
38+
39+
protected override void TearDown()
40+
{
41+
base.TearDown();
42+
43+
if (_proxyConnector != null)
44+
{
45+
_proxyConnector.Dispose();
46+
}
47+
}
48+
2849
protected override void Act()
2950
{
3051
try

src/Renci.SshNet.Tests/Classes/Connection/HttpConnectorTest_Connect_ProxyPasswordIsEmpty.cs

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.VisualStudio.TestTools.UnitTesting;
22
using Moq;
3+
using Renci.SshNet.Connection;
34
using Renci.SshNet.Tests.Common;
45
using System;
56
using System.Collections.Generic;
@@ -14,9 +15,11 @@ namespace Renci.SshNet.Tests.Classes.Connection
1415
public class HttpConnectorTest_Connect_ProxyPasswordIsEmpty : HttpConnectorTestBase
1516
{
1617
private ConnectionInfo _connectionInfo;
18+
private ProxyConnectionInfo _proxyConnectionInfo;
1719
private AsyncSocketListener _proxyServer;
1820
private bool _disconnected;
1921
private Socket _clientSocket;
22+
private IConnector _proxyConnector;
2023
private List<byte> _bytesReceivedByProxy;
2124
private string _expectedHttpRequest;
2225
private Socket _actual;
@@ -34,6 +37,7 @@ protected override void SetupData()
3437
"proxyUser",
3538
string.Empty,
3639
new KeyboardInteractiveAuthenticationMethod("user"));
40+
_proxyConnectionInfo = (ProxyConnectionInfo)_connectionInfo.ProxyConnection;
3741
_connectionInfo.Timeout = TimeSpan.FromMilliseconds(20);
3842
_expectedHttpRequest = string.Format("CONNECT {0}:{1} HTTP/1.0{2}" +
3943
"Proxy-Authorization: Basic cHJveHlVc2VyOg=={2}{2}",
@@ -43,8 +47,9 @@ protected override void SetupData()
4347
_bytesReceivedByProxy = new List<byte>();
4448
_disconnected = false;
4549
_clientSocket = SocketFactory.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
50+
_proxyConnector = ServiceFactory.CreateConnector(_proxyConnectionInfo, SocketFactory);
4651

47-
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _connectionInfo.ProxyPort));
52+
_proxyServer = new AsyncSocketListener(new IPEndPoint(IPAddress.Loopback, _proxyConnectionInfo.Port));
4853
_proxyServer.Disconnected += (socket) => _disconnected = true;
4954
_proxyServer.Connected += socket =>
5055
{
@@ -67,6 +72,8 @@ protected override void SetupMocks()
6772
{
6873
SocketFactoryMock.Setup(p => p.Create(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
6974
.Returns(_clientSocket);
75+
ServiceFactoryMock.Setup(p => p.CreateConnector(_proxyConnectionInfo, SocketFactory))
76+
.Returns(_proxyConnector);
7077
}
7178

7279
protected override void TearDown()
@@ -83,6 +90,11 @@ protected override void TearDown()
8390
_clientSocket.Shutdown(SocketShutdown.Both);
8491
_clientSocket.Close();
8592
}
93+
94+
if (_proxyConnector != null)
95+
{
96+
_proxyConnector.Dispose();
97+
}
8698
}
8799

88100
protected override void Act()

0 commit comments

Comments
 (0)