diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs new file mode 100644 index 00000000..598419b0 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Channels; +using Renci.SshNet.Common; + +namespace Renci.SshNet.Tests.Classes +{ + [TestClass] + public class ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse + { + private Mock _serviceFactoryMock; + private Mock _sessionMock; + private Mock _channelSessionMock; + private Mock _pipeStreamMock; + private ConnectionInfo _connectionInfo; + private ScpClient _scpClient; + private DirectoryInfo _directoryInfo; + private string _path; + private string _quotedPath; + private IList _uploadingRegister; + private SshException _actualException; + + [TestInitialize] + public void Setup() + { + Arrange(); + Act(); + } + + protected void Arrange() + { + var random = new Random(); + _connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd")); + _directoryInfo = new DirectoryInfo("destination"); + _path = "/home/sshnet/" + random.Next().ToString(CultureInfo.InvariantCulture); + _quotedPath = _path.ShellQuote(); + _uploadingRegister = new List(); + + _serviceFactoryMock = new Mock(MockBehavior.Strict); + _sessionMock = new Mock(MockBehavior.Strict); + _channelSessionMock = new Mock(MockBehavior.Strict); + _pipeStreamMock = new Mock(MockBehavior.Strict); + + var sequence = new MockSequence(); + _serviceFactoryMock.InSequence(sequence) + .Setup(p => p.CreateSession(_connectionInfo)) + .Returns(_sessionMock.Object); + _sessionMock.InSequence(sequence).Setup(p => p.Connect()); + _serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object); + _sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object); + _channelSessionMock.InSequence(sequence).Setup(p => p.Open()); + _channelSessionMock.InSequence(sequence) + .Setup(p => p.SendExecRequest(string.Format("scp -prf {0}", _quotedPath))).Returns(false); + _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); + _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); + + _scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object); + _scpClient.Uploading += (sender, args) => _uploadingRegister.Add(args); + _scpClient.Connect(); + } + + protected virtual void Act() + { + try + { + _scpClient.Download(_path, _directoryInfo); + Assert.Fail(); + } + catch (SshException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void UploadShouldHaveThrownSshException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual("Secure copy execution request was rejected by the server. Please consult the server logs.", _actualException.Message); + } + + [TestMethod] + public void SendExecRequestOnChannelSessionShouldBeInvokedOnce() + { + _channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -prf {0}", _quotedPath)), Times.Once); + } + + [TestMethod] + public void DisposeOnChannelShouldBeInvokedOnce() + { + _channelSessionMock.Verify(p => p.Dispose(), Times.Once); + } + + [TestMethod] + public void DisposeOnPipeStreamShouldBeInvokedOnce() + { + _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); + } + + [TestMethod] + public void UploadingShouldNeverHaveFired() + { + Assert.AreEqual(0, _uploadingRegister.Count); + } + } +} diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs new file mode 100644 index 00000000..f6cc45bd --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Channels; +using Renci.SshNet.Common; + +namespace Renci.SshNet.Tests.Classes +{ + [TestClass] + public class ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse + { + private Mock _serviceFactoryMock; + private Mock _sessionMock; + private Mock _channelSessionMock; + private Mock _pipeStreamMock; + private ConnectionInfo _connectionInfo; + private ScpClient _scpClient; + private FileInfo _fileInfo; + private string _path; + private string _quotedPath; + private IList _uploadingRegister; + private SshException _actualException; + + [TestInitialize] + public void Setup() + { + Arrange(); + Act(); + } + + protected void Arrange() + { + var random = new Random(); + _connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd")); + _fileInfo = new FileInfo("destination"); + _path = "/home/sshnet/" + random.Next().ToString(CultureInfo.InvariantCulture); + _quotedPath = _path.ShellQuote(); + _uploadingRegister = new List(); + + _serviceFactoryMock = new Mock(MockBehavior.Strict); + _sessionMock = new Mock(MockBehavior.Strict); + _channelSessionMock = new Mock(MockBehavior.Strict); + _pipeStreamMock = new Mock(MockBehavior.Strict); + + var sequence = new MockSequence(); + _serviceFactoryMock.InSequence(sequence) + .Setup(p => p.CreateSession(_connectionInfo)) + .Returns(_sessionMock.Object); + _sessionMock.InSequence(sequence).Setup(p => p.Connect()); + _serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object); + _sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object); + _channelSessionMock.InSequence(sequence).Setup(p => p.Open()); + _channelSessionMock.InSequence(sequence) + .Setup(p => p.SendExecRequest(string.Format("scp -pf {0}", _quotedPath))).Returns(false); + _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); + _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); + + _scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object); + _scpClient.Uploading += (sender, args) => _uploadingRegister.Add(args); + _scpClient.Connect(); + } + + protected virtual void Act() + { + try + { + _scpClient.Download(_path, _fileInfo); + Assert.Fail(); + } + catch (SshException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void UploadShouldHaveThrownSshException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual("Secure copy execution request was rejected by the server. Please consult the server logs.", _actualException.Message); + } + + [TestMethod] + public void SendExecRequestOnChannelSessionShouldBeInvokedOnce() + { + _channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -pf {0}", _quotedPath)), Times.Once); + } + + [TestMethod] + public void DisposeOnChannelShouldBeInvokedOnce() + { + _channelSessionMock.Verify(p => p.Dispose(), Times.Once); + } + + [TestMethod] + public void DisposeOnPipeStreamShouldBeInvokedOnce() + { + _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); + } + + [TestMethod] + public void UploadingShouldNeverHaveFired() + { + Assert.AreEqual(0, _uploadingRegister.Count); + } + } +} diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs new file mode 100644 index 00000000..cff3fb6f --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Channels; +using Renci.SshNet.Common; + +namespace Renci.SshNet.Tests.Classes +{ + [TestClass] + public class ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse + { + private Mock _serviceFactoryMock; + private Mock _sessionMock; + private Mock _channelSessionMock; + private Mock _pipeStreamMock; + private ConnectionInfo _connectionInfo; + private ScpClient _scpClient; + private Stream _destination; + private string _path; + private string _quotedPath; + private IList _uploadingRegister; + private SshException _actualException; + + [TestInitialize] + public void Setup() + { + Arrange(); + Act(); + } + + [TestCleanup] + public void Cleanup() + { + if (_destination != null) + { + _destination.Dispose(); + } + } + + protected void Arrange() + { + var random = new Random(); + _connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd")); + _destination = new MemoryStream(); + _path = "/home/sshnet/" + random.Next().ToString(CultureInfo.InvariantCulture); + _quotedPath = _path.ShellQuote(); + _uploadingRegister = new List(); + + _serviceFactoryMock = new Mock(MockBehavior.Strict); + _sessionMock = new Mock(MockBehavior.Strict); + _channelSessionMock = new Mock(MockBehavior.Strict); + _pipeStreamMock = new Mock(MockBehavior.Strict); + + var sequence = new MockSequence(); + _serviceFactoryMock.InSequence(sequence) + .Setup(p => p.CreateSession(_connectionInfo)) + .Returns(_sessionMock.Object); + _sessionMock.InSequence(sequence).Setup(p => p.Connect()); + _serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object); + _sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object); + _channelSessionMock.InSequence(sequence).Setup(p => p.Open()); + _channelSessionMock.InSequence(sequence) + .Setup(p => p.SendExecRequest(string.Format("scp -f {0}", _quotedPath))).Returns(false); + _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); + _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); + + _scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object); + _scpClient.Uploading += (sender, args) => _uploadingRegister.Add(args); + _scpClient.Connect(); + } + + protected virtual void Act() + { + try + { + _scpClient.Download(_path, _destination); + Assert.Fail(); + } + catch (SshException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void UploadShouldHaveThrownSshException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual("Secure copy execution request was rejected by the server. Please consult the server logs.", _actualException.Message); + } + + [TestMethod] + public void SendExecRequestOnChannelSessionShouldBeInvokedOnce() + { + _channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -f {0}", _quotedPath)), Times.Once); + } + + [TestMethod] + public void DisposeOnChannelShouldBeInvokedOnce() + { + _channelSessionMock.Verify(p => p.Dispose(), Times.Once); + } + + [TestMethod] + public void DisposeOnPipeStreamShouldBeInvokedOnce() + { + _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); + } + + [TestMethod] + public void UploadingShouldNeverHaveFired() + { + Assert.AreEqual(0, _uploadingRegister.Count); + } + } +} diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse.cs new file mode 100644 index 00000000..3f314d56 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Channels; +using Renci.SshNet.Common; + +namespace Renci.SshNet.Tests.Classes +{ + [TestClass] + public class ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse + { + private Mock _serviceFactoryMock; + private Mock _sessionMock; + private Mock _channelSessionMock; + private Mock _pipeStreamMock; + private ConnectionInfo _connectionInfo; + private ScpClient _scpClient; + private DirectoryInfo _directoryInfo; + private string _path; + private string _quotedPath; + private IList _uploadingRegister; + private SshException _actualException; + + [TestInitialize] + public void Setup() + { + Arrange(); + Act(); + } + + protected void Arrange() + { + var random = new Random(); + _connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd")); + _directoryInfo = new DirectoryInfo("source"); + _path = "/home/sshnet/" + random.Next().ToString(CultureInfo.InvariantCulture); + _quotedPath = _path.ShellQuote(); + _uploadingRegister = new List(); + + _serviceFactoryMock = new Mock(MockBehavior.Strict); + _sessionMock = new Mock(MockBehavior.Strict); + _channelSessionMock = new Mock(MockBehavior.Strict); + _pipeStreamMock = new Mock(MockBehavior.Strict); + + var sequence = new MockSequence(); + _serviceFactoryMock.InSequence(sequence) + .Setup(p => p.CreateSession(_connectionInfo)) + .Returns(_sessionMock.Object); + _sessionMock.InSequence(sequence).Setup(p => p.Connect()); + _serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object); + _sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object); + _channelSessionMock.InSequence(sequence).Setup(p => p.Open()); + _channelSessionMock.InSequence(sequence) + .Setup(p => p.SendExecRequest(string.Format("scp -rt {0}", _quotedPath))).Returns(false); + _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); + _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); + + _scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object); + _scpClient.Uploading += (sender, args) => _uploadingRegister.Add(args); + _scpClient.Connect(); + } + + protected virtual void Act() + { + try + { + _scpClient.Upload(_directoryInfo, _path); + Assert.Fail(); + } + catch (SshException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void UploadShouldHaveThrownSshException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual("Secure copy execution request was rejected by the server. Please consult the server logs.", _actualException.Message); + } + + [TestMethod] + public void SendExecREquestOnChannelSessionShouldBeInvokedOnce() + { + _channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -rt {0}", _quotedPath)), Times.Once); + } + + [TestMethod] + public void DisposeOnChannelShouldBeInvokedOnce() + { + _channelSessionMock.Verify(p => p.Dispose(), Times.Once); + } + + [TestMethod] + public void DisposeOnPipeStreamShouldBeInvokedOnce() + { + _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); + } + + [TestMethod] + public void UploadingShouldNeverHaveFired() + { + Assert.AreEqual(0, _uploadingRegister.Count); + } + } +} diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs index 034e244f..0656fc35 100644 --- a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse.cs @@ -97,7 +97,7 @@ namespace Renci.SshNet.Tests.Classes } [TestMethod] - public void SendExecREquestOnChannelSessionShouldBeInvokedOnce() + public void SendExecRequestOnChannelSessionShouldBeInvokedOnce() { _channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -t {0}", _quotedPath)), Times.Once); } diff --git a/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse.cs b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse.cs new file mode 100644 index 00000000..a7ca9024 --- /dev/null +++ b/src/Renci.SshNet.Tests/Classes/ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Renci.SshNet.Channels; +using Renci.SshNet.Common; + +namespace Renci.SshNet.Tests.Classes +{ + [TestClass] + public class ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse + { + private Mock _serviceFactoryMock; + private Mock _sessionMock; + private Mock _channelSessionMock; + private Mock _pipeStreamMock; + private ConnectionInfo _connectionInfo; + private ScpClient _scpClient; + private Stream _source; + private string _path; + private string _quotedPath; + private IList _uploadingRegister; + private SshException _actualException; + + [TestInitialize] + public void Setup() + { + Arrange(); + Act(); + } + + [TestCleanup] + public void Cleanup() + { + if (_source != null) + { + _source.Dispose(); + } + } + + protected void Arrange() + { + var random = new Random(); + _connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd")); + _source = new MemoryStream(); + _path = "/home/sshnet/" + random.Next().ToString(CultureInfo.InvariantCulture); + _quotedPath = _path.ShellQuote(); + _uploadingRegister = new List(); + + _serviceFactoryMock = new Mock(MockBehavior.Strict); + _sessionMock = new Mock(MockBehavior.Strict); + _channelSessionMock = new Mock(MockBehavior.Strict); + _pipeStreamMock = new Mock(MockBehavior.Strict); + + var sequence = new MockSequence(); + _serviceFactoryMock.InSequence(sequence) + .Setup(p => p.CreateSession(_connectionInfo)) + .Returns(_sessionMock.Object); + _sessionMock.InSequence(sequence).Setup(p => p.Connect()); + _serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object); + _sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object); + _channelSessionMock.InSequence(sequence).Setup(p => p.Open()); + _channelSessionMock.InSequence(sequence) + .Setup(p => p.SendExecRequest(string.Format("scp -t {0}", _quotedPath))).Returns(false); + _channelSessionMock.InSequence(sequence).Setup(p => p.Dispose()); + _pipeStreamMock.As().InSequence(sequence).Setup(p => p.Dispose()); + + _scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object); + _scpClient.Uploading += (sender, args) => _uploadingRegister.Add(args); + _scpClient.Connect(); + } + + protected virtual void Act() + { + try + { + _scpClient.Upload(_source, _path); + Assert.Fail(); + } + catch (SshException ex) + { + _actualException = ex; + } + } + + [TestMethod] + public void UploadShouldHaveThrownSshException() + { + Assert.IsNotNull(_actualException); + Assert.IsNull(_actualException.InnerException); + Assert.AreEqual("Secure copy execution request was rejected by the server. Please consult the server logs.", _actualException.Message); + } + + [TestMethod] + public void SendExecRequestOnChannelSessionShouldBeInvokedOnce() + { + _channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -t {0}", _quotedPath)), Times.Once); + } + + [TestMethod] + public void DisposeOnChannelShouldBeInvokedOnce() + { + _channelSessionMock.Verify(p => p.Dispose(), Times.Once); + } + + [TestMethod] + public void DisposeOnPipeStreamShouldBeInvokedOnce() + { + _pipeStreamMock.As().Verify(p => p.Dispose(), Times.Once); + } + + [TestMethod] + public void UploadingShouldNeverHaveFired() + { + Assert.AreEqual(0, _uploadingRegister.Count); + } + } +} diff --git a/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj b/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj index 7cc106fb..cebdad5d 100644 --- a/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj +++ b/src/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj @@ -211,8 +211,13 @@ + + + + + diff --git a/src/Renci.SshNet/ScpClient.NET.cs b/src/Renci.SshNet/ScpClient.NET.cs index 1ccf3296..f7f37cd3 100644 --- a/src/Renci.SshNet/ScpClient.NET.cs +++ b/src/Renci.SshNet/ScpClient.NET.cs @@ -22,6 +22,7 @@ namespace Renci.SshNet /// is null. /// is null or empty. /// A directory with the specified path exists on the remote host. + /// The secure copy execution request was rejected by the server. public void Upload(FileInfo fileInfo, string path) { if (fileInfo == null) @@ -36,7 +37,9 @@ namespace Renci.SshNet channel.Open(); if (!channel.SendExecRequest(string.Format("scp -t {0}", path.ShellQuote()))) - throw new SshException("Secure copy execution request was rejected by the server. Please consult the server logs."); + { + throw SecureExecutionRequestRejectedException(); + } CheckReturnCode(input); using (var source = fileInfo.OpenRead()) @@ -56,6 +59,7 @@ namespace Renci.SshNet /// fileSystemInfo /// is null or empty. /// exists on the remote host, and is not a directory. + /// The secure copy execution request was rejected by the server. public void Upload(DirectoryInfo directoryInfo, string path) { if (directoryInfo == null) @@ -70,7 +74,10 @@ namespace Renci.SshNet channel.Open(); // start recursive upload - channel.SendExecRequest(string.Format("scp -rt {0}", path.ShellQuote())); + if (!channel.SendExecRequest(string.Format("scp -rt {0}", path.ShellQuote()))) + { + throw SecureExecutionRequestRejectedException(); + } CheckReturnCode(input); UploadTimes(channel, input, directoryInfo); @@ -87,6 +94,7 @@ namespace Renci.SshNet /// is null. /// is null or empty. /// exists on the remote host, and is not a regular file. + /// The secure copy execution request was rejected by the server. public void Download(string filename, FileInfo fileInfo) { if (string.IsNullOrEmpty(filename)) @@ -101,7 +109,10 @@ namespace Renci.SshNet channel.Open(); // Send channel command request - channel.SendExecRequest(string.Format("scp -pf {0}", filename.ShellQuote())); + if (!channel.SendExecRequest(string.Format("scp -pf {0}", filename.ShellQuote()))) + { + throw SecureExecutionRequestRejectedException(); + } // Send reply SendSuccessConfirmation(channel); @@ -117,6 +128,7 @@ namespace Renci.SshNet /// is null or empty. /// is null. /// File or directory with the specified path does not exist on the remote host. + /// The secure copy execution request was rejected by the server. public void Download(string directoryName, DirectoryInfo directoryInfo) { if (string.IsNullOrEmpty(directoryName)) @@ -131,7 +143,10 @@ namespace Renci.SshNet channel.Open(); // Send channel command request - channel.SendExecRequest(string.Format("scp -prf {0}", directoryName.ShellQuote())); + if (!channel.SendExecRequest(string.Format("scp -prf {0}", directoryName.ShellQuote()))) + { + throw SecureExecutionRequestRejectedException(); + } // Send reply SendSuccessConfirmation(channel); diff --git a/src/Renci.SshNet/ScpClient.cs b/src/Renci.SshNet/ScpClient.cs index 6171614a..4f1acda8 100644 --- a/src/Renci.SshNet/ScpClient.cs +++ b/src/Renci.SshNet/ScpClient.cs @@ -172,6 +172,7 @@ namespace Renci.SshNet /// The to upload. /// A relative or absolute path for the remote file. /// A directory with the specified path exists on the remote host. + /// The secure copy execution request was rejected by the server. public void Upload(Stream source, string path) { using (var input = ServiceFactory.CreatePipeStream()) @@ -183,7 +184,9 @@ namespace Renci.SshNet // pass the full path to ensure the server does not create the directory part // as a file in case the directory does not exist if (!channel.SendExecRequest(string.Format("scp -t {0}", path.ShellQuote()))) - return; + { + throw SecureExecutionRequestRejectedException(); + } CheckReturnCode(input); // specify a zero-length file name to avoid creating a file with absolute @@ -201,10 +204,7 @@ namespace Renci.SshNet /// is null or contains only whitespace characters. /// is null. /// exists on the remote host, and is not a regular file. - /// - /// Method calls made by this method to , may under certain conditions result - /// in exceptions thrown by the stream. - /// + /// The secure copy execution request was rejected by the server. public void Download(string filename, Stream destination) { if (filename.IsNullOrWhiteSpace()) @@ -220,7 +220,10 @@ namespace Renci.SshNet channel.Open(); // Send channel command request - channel.SendExecRequest(string.Format("scp -f {0}", filename.ShellQuote())); + if (!channel.SendExecRequest(string.Format("scp -f {0}", filename.ShellQuote()))) + { + throw SecureExecutionRequestRejectedException(); + } SendSuccessConfirmation(channel); // Send reply var message = ReadString(input); @@ -424,5 +427,10 @@ namespace Renci.SshNet throw new ScpException(ConnectionInfo.Encoding.GetString(readBytes, 0, readBytes.Length)); return ConnectionInfo.Encoding.GetString(readBytes, 0, readBytes.Length); } + + private static SshException SecureExecutionRequestRejectedException() + { + throw new SshException("Secure copy execution request was rejected by the server. Please consult the server logs."); + } } }