Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes and improvements for port forwarding tests #6

Merged
merged 4 commits into from
Apr 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion docker/DockerFile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ RUN apk add --no-cache syslog-ng && \
addgroup sshnetadm sudo && \
dos2unix /opt/sshnet/* && \
# install shadow package; we use chage command in this package to expire/unexpire password of the sshnet user
apk add --no-cache shadow
apk add --no-cache shadow && \
# allow us to use telnet command; we use this in the remote port forwarding tests
apk --no-cache add busybox-extras && \
# install full-fledged ps command
apk add --no-cache procps

EXPOSE 22 22

Expand Down
1 change: 1 addition & 0 deletions src/SshNetTests/Common/RemoteSshdConfigExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public static void Reset(this RemoteSshdConfig remoteSshdConfig)
remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, DefaultAuthenticationMethods)
.WithChallengeResponseAuthentication(false)
.WithKeyboardInteractiveAuthentication(false)
.PrintMotd()
.WithLogLevel(LogLevel.Debug3)
.ClearHostKeyFiles()
.AddHostKeyFile(HostKeyFile.Rsa.FilePath)
Expand Down
27 changes: 26 additions & 1 deletion src/SshNetTests/PrivateKeyAuthenticationTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Renci.SshNet;
using SshNet.TestTools.OpenSSH;
using SshNetTests.Common;

namespace SshNetTests
Expand Down Expand Up @@ -29,22 +30,46 @@ public void TearDown()
[TestMethod]
public void Ecdsa256()
{
_remoteSshdConfig.AddPublicKeyAcceptedAlgorithms(PublicKeyAlgorithm.EcdsaSha2Nistp256)
.Update()
.Restart();

var connectionInfo = _connectionInfoFactory.Create(CreatePrivateKeyAuthenticationMethod("key_ecdsa_256_openssh"));

using (var client = new SshClient(connectionInfo))
{
client.Connect();
client.Disconnect();
}
}

[TestMethod]
public void Ecdsa384()
{
_remoteSshdConfig.AddPublicKeyAcceptedAlgorithms(PublicKeyAlgorithm.EcdsaSha2Nistp384)
.Update()
.Restart();

var connectionInfo = _connectionInfoFactory.Create(CreatePrivateKeyAuthenticationMethod("key_ecdsa_384_openssh"));

using (var client = new SshClient(connectionInfo))
{
client.Connect();
}
}

[TestMethod]
public void EcdsaA521()
{
_remoteSshdConfig.AddPublicKeyAcceptedAlgorithms(PublicKeyAlgorithm.EcdsaSha2Nistp521)
.Update()
.Restart();

var connectionInfo = _connectionInfoFactory.Create(CreatePrivateKeyAuthenticationMethod("key_ecdsa_521_openssh"));

using (var client = new SshClient(connectionInfo))
{
client.Connect();
}
}

private PrivateKeyAuthenticationMethod CreatePrivateKeyAuthenticationMethod(string keyResource)
Expand Down
26 changes: 26 additions & 0 deletions src/SshNetTests/RemoteSshd.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,32 @@ public RemoteSshdConfig WithKeyboardInteractiveAuthentication(bool value)
return this;
}

/// <summary>
/// Specifies whether <c>sshd</c> should print /etc/motd when a user logs in interactively.
/// </summary>
/// <param name="value"><see langword="true"/> if <c>sshd</c> should print /etc/motd when a user logs in interactively.</param>
/// <returns>
/// The current <see cref="RemoteSshdConfig"/> instance.
/// </returns>
public RemoteSshdConfig PrintMotd(bool? value = true)
{
_config.PrintMotd = value;
return this;
}

/// <summary>
/// Specifies whether TCP forwarding is permitted.
/// </summary>
/// <param name="value"><see langword="true"/> to allow TCP forwarding.</param>
/// <returns>
/// The current <see cref="RemoteSshdConfig"/> instance.
/// </returns>
public RemoteSshdConfig AllowTcpForwarding(bool? value = true)
{
_config.AllowTcpForwarding = value;
return this;
}

public RemoteSshdConfig WithAuthenticationMethods(string user, string authenticationMethods)
{
var sshNetMatch = _config.Matches.FirstOrDefault(m => m.Users.Contains(user));
Expand Down
216 changes: 214 additions & 2 deletions src/SshNetTests/SftpTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4846,8 +4846,220 @@ public void Sftp_Open_Append_Write_FileDoesNotExist()
}
}



[TestMethod]
public void Sftp_Open_PathAndMode_ModeIsCreate_FileDoesNotExist()
{
const string remoteFile = "/home/sshnet/test";

using (var client = new SftpClient(_connectionInfoFactory.Create()))
{
client.Connect();

if (client.Exists(remoteFile))
{
client.DeleteFile(remoteFile);
}

try
{
#region Verify if merely opening the file for create creates a zero-byte file

using (client.Open(remoteFile, FileMode.Create))
{
}

Assert.IsTrue(client.Exists(remoteFile));

var attributes = client.GetAttributes(remoteFile);
Assert.IsTrue(attributes.IsRegularFile);
Assert.AreEqual(0L, attributes.Size);

#endregion Verify if merely opening the file for create creates a zero-byte file

client.DeleteFile(remoteFile);

#region Verify if content is actually written to the file

var content = GenerateRandom(100);

using (var s = client.Open(remoteFile, FileMode.Create))
{
s.Write(content, 0, content.Length);
}

using (var downloaded = new MemoryStream())
{
client.DownloadFile(remoteFile, downloaded);
downloaded.Position = 0;
Assert.AreEqual(CreateHash(content), CreateHash(downloaded));
}

#endregion Verify if content is actually written to the file
}
finally
{
if (client.Exists(remoteFile))
{
client.DeleteFile(remoteFile);
}
}
}
}

[TestMethod]
public void Sftp_Open_PathAndMode_ModeIsCreate_ExistingFile()
{
const string remoteFile = "/home/sshnet/test";
const int fileSize = 5 * 1024;
var newContent = new byte[] { 0x07, 0x03, 0x02, 0x0b };

using (var client = new SftpClient(_connectionInfoFactory.Create()))
using (var input = CreateMemoryStream(fileSize))
{
client.Connect();

if (client.Exists(remoteFile))
{
client.DeleteFile(remoteFile);
}

try
{
input.Position = 0;
client.UploadFile(input, remoteFile);

using (var stream = client.Open(remoteFile, FileMode.Create))
{
// Verify if merely opening the file for create overwrites the file
var attributes = client.GetAttributes(remoteFile);
Assert.IsTrue(attributes.IsRegularFile);
Assert.AreEqual(0L, attributes.Size);

stream.Write(newContent, 0, newContent.Length);
stream.Position = 0;

Assert.AreEqual(CreateHash(newContent), CreateHash(stream));
}
}
finally
{
if (client.Exists(remoteFile))
{
client.DeleteFile(remoteFile);
}
}
}
}

[TestMethod]
public void Sftp_Open_PathAndModeAndAccess_ModeIsCreate_AccessIsReadWrite_FileDoesNotExist()
{
const string remoteFile = "/home/sshnet/test";

using (var client = new SftpClient(_connectionInfoFactory.Create()))
{
client.Connect();

if (client.Exists(remoteFile))
{
client.DeleteFile(remoteFile);
}

try
{
#region Verify if merely opening the file for create creates a zero-byte file

using (client.Open(remoteFile, FileMode.Create, FileAccess.ReadWrite))
{
}

Assert.IsTrue(client.Exists(remoteFile));

var attributes = client.GetAttributes(remoteFile);
Assert.IsTrue(attributes.IsRegularFile);
Assert.AreEqual(0L, attributes.Size);

#endregion Verify if merely opening the file for create creates a zero-byte file

client.DeleteFile(remoteFile);

#region Verify if content is actually written to the file

var content = GenerateRandom(100);

using (var s = client.Open(remoteFile, FileMode.Create, FileAccess.ReadWrite))
{
s.Write(content, 0, content.Length);
}

using (var downloaded = new MemoryStream())
{
client.DownloadFile(remoteFile, downloaded);
downloaded.Position = 0;
Assert.AreEqual(CreateHash(content), CreateHash(downloaded));
}

#endregion Verify if content is actually written to the file
}
finally
{
if (client.Exists(remoteFile))
{
client.DeleteFile(remoteFile);
}
}
}
}

[TestMethod]
public void Sftp_Open_PathAndModeAndAccess_ModeIsCreate_AccessIsReadWrite_ExistingFile()
{
const string remoteFile = "/home/sshnet/test";
const int fileSize = 5 * 1024;
var newContent = new byte[] { 0x07, 0x03, 0x02, 0x0b };

using (var client = new SftpClient(_connectionInfoFactory.Create()))
using (var input = CreateMemoryStream(fileSize))
{
client.Connect();

if (client.Exists(remoteFile))
{
client.DeleteFile(remoteFile);
}

try
{
input.Position = 0;
client.UploadFile(input, remoteFile);

using (var stream = client.Open(remoteFile, FileMode.Create, FileAccess.ReadWrite))
{
// Verify if merely opening the file for create overwrites the file
var attributes = client.GetAttributes(remoteFile);
Assert.IsTrue(attributes.IsRegularFile);
Assert.AreEqual(0L, attributes.Size);

stream.Write(newContent, 0, newContent.Length);
stream.Position = 0;

Assert.AreEqual(CreateHash(newContent), CreateHash(stream));
}
}
finally
{
if (client.Exists(remoteFile))
{
client.DeleteFile(remoteFile);
}
}
}
}

[TestMethod]
public void Sftp_Open_Create_Write_ExistingFile()
public void Sftp_Open_PathAndModeAndAccess_ModeIsCreate_AccessIsWrite_ExistingFile()
{
const string remoteFile = "/home/sshnet/test";

Expand Down Expand Up @@ -4893,7 +5105,7 @@ public void Sftp_Open_Create_Write_ExistingFile()
}

[TestMethod]
public void Sftp_Open_Create_Write_FileDoesNotExist()
public void Sftp_Open_PathAndModeAndAccess_ModeIsCreate_AccessIsWrite_FileDoesNotExist()
{
const string remoteFile = "/home/sshnet/test";

Expand Down
Loading