Skip to content

Releases: sshnet/SSH.NET

2026.0.0

Choose a tag to compare

@Rob-Hague Rob-Hague released this 09 Aug 18:15
Immutable release. Only release title and notes can be modified.
7b2fd3d

Highlights

  • Add overloads of DownloadFileAsync and UploadFileAsync taking an IProgress argument (#1771)
  • Significantly reduced memory allocations in all scenarios. For SFTP:
Operation File size Version Allocated
SFTP Download 1MB 2025.1.0 3.2MB
SFTP Download 1MB 2026.0.0 0.1MB
SFTP Download 8MB 2025.1.0 24.8MB
SFTP Download 8MB 2026.0.0 0.7MB
SFTP Download 64MB 2025.1.0 197.8MB
SFTP Download 64MB 2026.0.0 4.8MB
SFTP Upload 1MB 2025.1.0 4.1MB
SFTP Upload 1MB 2026.0.0 0.0MB
SFTP Upload 8MB 2025.1.0 32.5MB
SFTP Upload 8MB 2026.0.0 0.3MB
SFTP Upload 64MB 2025.1.0 259.5MB
SFTP Upload 64MB 2026.0.0 1.9MB

Breaking changes

  • None known

What's Changed

New Contributors

Full Changelog: 2025.1.0...2026.0.0

2025.1.0

Choose a tag to compare

@Rob-Hague Rob-Hague released this 27 Oct 20:56
6390ede

Highlights

  • Add DownloadFileAsync and UploadFileAsync to SftpClient (#1634)
  • Much improved performance of SftpFileStream in consecutive read (e.g. SftpFileStream.CopyTo) scenarios (#1705)

Breaking changes:

  • SftpFileStream previously had some incomplete synchronisation for multi-threaded access, but was not advertised nor fully functioning as thread safe. This synchronisation was removed in #1705. When accessing an SftpFileStream instance from multiple threads simultaneously, ensure there exists appropriate synchronisation.
  • SftpClient.CreateText and WriteAll{Bytes/Text/Lines} were changed in #1686 to truncate the file before writing if it exists, to align with the equivalent methods on System.IO.File. Given that the prior behaviour was 14 years old, the change treads the line between breaking change and bug fix.
  • IEnumerable<string> ReadLines on SftpClient was updated in #1681 to download and yield lines during enumeration rather than reading them all up front and returning the result. This means that the connection must be active during enumeration. When storing the result of ReadLines for later use, consider using string[] ReadAllLines instead.

What's Changed

New Contributors

Full Changelog: 2025.0.0...2025.1.0

API diff
  namespace Renci.SshNet
  {
      public class ConnectionInfo
      {
+         public Microsoft.Extensions.Logging.ILoggerFactory? LoggerFactory { get; set; }
      }
      public interface ISftpClient : Renci.SshNet.IBaseClient
      {
+         System.Threading.Tasks.Task DownloadFileAsync(string path, System.IO.Stream output, System.Threading.CancellationToken cancellationToken = default);
+         System.Threading.Tasks.Task<Renci.SshNet.Sftp.SftpFileAttributes> GetAttributesAsync(string path, System.Threading.CancellationToken cancellationToken);
+         System.Threading.Tasks.Task UploadFileAsync(System.IO.Stream input, string path, System.Threading.CancellationToken cancellationToken = default);
      }
      public class SftpClient : Renci.SshNet.BaseClient, Renci.SshNet.ISftpClient, Renci.SshNet.IBaseClient
      {
+         public System.Threading.Tasks.Task DownloadFileAsync(string path, System.IO.Stream output, System.Threading.CancellationToken cancellationToken = default);
+         public System.Threading.Tasks.Task<Renci.SshNet.Sftp.SftpFileAttributes> GetAttributesAsync(string path, System.Threading.CancellationToken cancellationToken);
+         public System.Threading.Tasks.Task UploadFileAsync(System.IO.Stream input, string path, System.Threading.CancellationToken cancellationToken = default);
      }
      public sealed class ShellStream
      {
+         public void ChangeWindowSize(uint columns, uint rows, uint width, uint height);
      }
  }
  namespace Renci.SshNet.Common
  {
      public class SftpPathNotFoundException : Renci.SshNet.Common.SftpException
      {
+         public SftpPathNotFoundException(string? message, string? path, System.Exception? innerException);
+         public SftpPathNotFoundException(string? message, string? path);
+         public string? Path { get; }
      }
+     public class SftpException : Renci.SshNet.Common.SshException
+     {
+         public SftpException(Renci.SshNet.Sftp.StatusCode statusCode, string? message, System.Exception? innerException);
+         public SftpException(Renci.SshNet.Sftp.StatusCode statusCode, string? message);
+         public SftpException(Renci.SshNet.Sftp.StatusCode statusCode);
+         public Renci.SshNet.Sftp.StatusCode StatusCode { get; }
+     }
  }
  namespace Renci.SshNet.Security
  {
+     public class KeyExchangeDiffieHellman : Renci.SshNet.Security.KeyExchange
+     {
+         public KeyExchangeDiffieHellman(string name, Org.BouncyCastle.Crypto.Parameters.DHParameters parameters, System.Security.Cryptography.HashAlgorithmName hashAlgorithm);
+         public override void Start(Renci.SshNet.Session session, Renci.SshNet.Messages.Transport.KeyExchangeInitMessage message, bool sendClientInitMessage);
+         public override string Name { get; }
+     }
+     public class KeyExchangeDiffieHellmanGroupExchange : Renci.SshNet.Security.KeyExchange
+     {
+         public KeyExchangeDiffieHellmanGroupExchange(string name, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, uint minimumGroupSize, uint preferredGroupSize, uint maximumGroupSize);
+         public KeyExchangeDiffieHellmanGroupExchange(string name, System.Security.Cryptography.HashAlgorithmName hashAlgorithm);
+         public override void Start(Renci.SshNet.Session session, Renci.SshNet.Messages.Transport.KeyExchangeInitMessa...
Read more

2025.0.0

Choose a tag to compare

@Rob-Hague Rob-Hague released this 18 Apr 19:44

Highlights

  • Add support for post-quantum key exchange methods sntrup761x25519-sha512 and mlkem768x25519-sha256
  • Add support for PuTTY private key files
  • Add logging capability via Microsoft.Extensions.Logging

Breaking changes

  • Support for DSA was dropped in #1558
  • CipherPadding was deleted in #1546 and uses replaced with Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding
  • See the full API diff at the end

What's Changed

New Contributors

Full Changelog: 2024.2.0...2025.0.0

API diff
  namespace Renci.SshNet
  {
      public abstract class AuthenticationMethod
      {
+         public void Dispose();
+         protected virtual void Dispose(bool disposing);
      }
      public class ConnectionInfo
      {
-         public System.Collections.Generic.IDictionary<string, System.Func<Renci.SshNet.Compression.Compressor>> CompressionAlgorithms { get; }
+         public Renci.SshNet.IOrderedDictionary<string, System.Func<Renci.SshNet.Compression.Compressor>> CompressionAlgorithms { get; }
-         public System.Collections.Generic.IDictionary<string, Renci.SshNet.CipherInfo> Encryptions { get; }
+         public Renci.SshNet.IOrderedDictionary<string, Renci.SshNet.CipherInfo> Encryptions { get; }
-         public System.Collections.Generic.IDictionary<string, Renci.SshNet.HashInfo> HmacAlgorithms { get; }
+         public Renci.SshNet.IOrderedDictionary<string, Renci.SshNet.HashInfo> HmacAlgorithms { get; }
-         public System.Collections.Generic.IDictionary<string, System.Func<byte[], Renci.SshNet.Security.KeyHostAlgorithm>> HostKeyAlgorithms { get; }
+         public Renci.SshNet.IOrderedDictionary<string, System.Func<byte[], Renci.SshNet.Security.KeyHostAlgorithm>> HostKeyAlgorithms { get; }
-         public System.Collections.Generic.IDictionary<string, System.Func<Renci.SshNet.Security.IKeyExchange>> KeyExchangeAlgorithms { get; }
+         public Renci.SshNet.IOrderedDictionary<string, System.Func<Renci.SshNet.Security.IKeyExchange>> KeyExchangeAlgorithms { get; }
      }
      public interface ISftpClient : Renci.SshNet.IBaseClient
      {
+         System.Threading.Tasks.Task<bool> ExistsAsync(string path, System.Threading.CancellationToken cancellationToken = null);
+         System.Threading.Tasks.Task<Renci.SshNet.Sftp.ISftpFile> GetAsync(string path, System.Threading.CancellationToken cancellationToken);
      }
      public class KeyboardInteractiveAuthenticationMethod : Renci.SshNet.AuthenticationMethod
      {
-         public void Dispose();
-         protected virtual void Dispose(bool disposing);
+         protected override void Dispose(bool disposing);
      }
      public class NoneAuthenticationMethod : Renci.SshNet.AuthenticationMethod
      {
-         public void Dispose();
-         protected virtual void Dispose(bool disposing);
+         protected override void Dispose(bool disposing);
      }
      public class PasswordAuthenticationMethod : Renci.SshNet.AuthenticationMethod
      {
-         public void Dispose();
-         protected virtual void Dispose(bool disposing);
+         protected override void Dispose(bool disposing);
      }
      public class PrivateKeyAuthenticationMethod : Renci.SshNet.AuthenticationMethod
      {
-         public void Dispose();
-         protected virtual void Dispose(bool disposing);
+         protected override void Dispose(bool disposing);
      }
+     public interface IOrderedDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>
+     {
+         bool ContainsKey(TKey key);
+         bool ContainsValue(TValue value);
+         System.Collections.Generic.KeyValuePair<TKey, TValue> GetAt(int index);
+         int IndexOf(TKey key);
+         void Insert(int index, TKey key, TValue value);
+         bool Remove(TKey key, out TValue value);
+         void RemoveAt(int index);
+         void SetAt(int index, TKey key, TValue value);
+         void SetAt(int index, TValue value);
+         void SetPosition(TKey key, int newIndex);
+         void SetPosition(int index, int newIndex);
+         bool TryAdd(TKey key, TValue value, out int index);
+         bool TryAdd(TKey key, TValue value);
+         bool TryGetValue(TKey key, out TValue value, out int index);
+         bool TryGetValue(TKey key, out TValue value);
+         int Count { get; }
+         TValue this[TKey key] { get; set; }
+       ...
Read more

2024.2.0

Choose a tag to compare

@Rob-Hague Rob-Hague released this 11 Nov 21:40

New features

  • Add support for PKCS#8 private key files
  • Add additional async overloads on SftpClient
  • Add support for OpenSSH certificates
  • Add support for chacha20-poly1305@openssh.com cipher algorithm
  • Increase support for aes*-gcm@openssh.com and zlib@openssh.com on lower targets

This release takes a dependency on BouncyCastle in an effort to eliminate primitive crypto code from the library. It also takes a dependency on System.Formats.Asn1 on lower targets.

Breaking changes

  • A number of legacy algorithms were dropped in #1442
  • The implementation of DSA was changed from using handwritten code to using System.Cryptography in #1458. See the PR description for behaviour changes this could cause.
  • Renci.SshNet.Common.BigInteger was deleted and its uses replaced with System.Numerics.BigInteger in #1469
  • Renci.SshNet.Common.DerData and Renci.SshNet.Common.ObjectIdentifier were deleted in #1490 and uses replaced with System.Formats.Asn1
  • See the full API diff at the end

What's Changed

New Contributors

Full Changelog: 2024.1.0...2024.2.0

API diff
namespace Renci.SshNet
{
     public interface IBaseClient : System.IDisposable
     {
+        event System.EventHandler<Renci.SshNet.Common.SshIdentificationEventArgs>? ServerIdentificationReceived;
     }

     public interface ISftpClient : Renci.SshNet.IBaseClient, System.IDisposable
     {
+        System.Threading.Tasks.Task ChangeDirectoryAsync(string path, System.Threading.CancellationToken cancellationToken = default);
+        System.Threading.Tasks.Task CreateDirectoryAsync(string path, System.Threading.CancellationToken cancellationToken = default);
+        System.Threading.Tasks.Task DeleteAsync(string path, System.Threading.CancellationToken cancellationToken = default);
+        System.Threading.Tasks.Task DeleteDirectoryAsync(string path, System.Threading.CancellationToken cancellationToken = default);
     }

+    public interface ISshClient : Renci.SshNet.IBaseClient, System.IDisposable
+    {
+        System.Collections.Generic.IEnumerable<Renci.SshNet.ForwardedPort> ForwardedPorts { get; }
+        void AddForwardedPort(Renci.SshNet.ForwardedPort port);
+        Renci.SshNet.SshCommand CreateCommand(string commandText);
+        Renci.SshNet.SshCommand CreateCommand(string commandText, System.Text.Encoding encoding);
+        Renci.SshNet.Shell CreateShell(System.IO.Stream input, System.IO.Stream output, System.IO.Stream extendedOutput);
+        Renci.SshNet.Shell CreateShell(System.Text.Encoding encoding, string input, System.IO.Stream output, System.IO.Stream extendedOutput);
+        Renci.SshNet.Shell CreateShell(System.IO.Stream input, System.IO.Stream output, System.IO.Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, System.Collections.Generic.IDictionary<Renci.SshNet.Common.TerminalModes, uint> terminalModes);
+        Renci.SshNet.Shell CreateShell(System.IO.Stream input, System.IO.Stream output, System.IO.Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, System.Collections.Generic.IDictionary<Renci.SshNet.Common.TerminalModes, uint>? terminalModes, int bufferSize);
+        Renci.SshNet.Shell CreateShell(System.Text.Encoding encoding, string input, System.IO.Stream output, System.IO.Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, System.Collections.Generic.IDictionary<Renci.SshNet.Common.TerminalModes, uint> terminalModes);
+        Renci.SshNet.Shell CreateShell(System.Text.Encoding encoding, string input, System.IO.Stream output, System.IO.Stream extendedOutput, string terminalName, uint columns, uint rows, uint width, uint height, System.Collections.Generic.IDictionary<Renci.SshNet.Common.TerminalModes, uint>? terminalModes, int bufferSize);
+        Renci.SshNet.Shell CreateShellNoTerminal(System.IO.Stream input, System.IO.Stream output, System.IO.Stream extendedOutput, int bufferSize = -1);
+        Renci.SshNet.ShellStream CreateShellStream(string terminalName, uint columns, uint rows, uint width, uint height, int bufferSize);
+        Renci.SshNet.ShellStream CreateShellStream(string terminalName, uint columns, uint rows, uint width, uint height, int bufferSize, System.Collections.Generic.IDictionary<Renci.SshNet.Common.TerminalModes, uint>? terminalModeValues);
+        Renci.SshNet.ShellStream CreateShellStreamNoTerminal(int bufferSize = -1);
+        void RemoveForwardedPort(Renci.SshNet.ForwardedPort port);
+        Renci.SshNet.SshCommand RunCommand(string commandText);
+    }

     public class PrivateKeyConnectionInfo : ...
Read more

2024.1.0

Choose a tag to compare

@Rob-Hague Rob-Hague released this 28 Jun 07:06
a553152

New features:

  • Add support for aes*-gcm@openssh.com cipher algorithms on .NET 6+
  • Add cancellation of SshCommand via signals
  • Add SshCommand.ExecuteAsync
  • Add support for zlib@openssh.com compression algorithm on .NET 6+

Breaking changes:

  • SshCommand.ExitStatus was changed in #1423 from returning int to returning int? to reflect the fact that an exit status may not always be returned.
  • PipeStream (which provides the implementation of SshCommand.OutputStream and ExtendedOutputStream) was rewritten in #1399 to fix a number of bugs and become more "stream-like". As such:
    • It may now block where previously it may have returned 0 prematurely
    • It may now return partial data where previously it may have blocked until a certain amount of data was available.
    • The properties BlockLastReadBuffer and MaxBufferLength have been removed.
  • CommandAsyncResult was deleted in #1426
  • RsaCipher, AsymmetricCipher and CipherDigitalSignature were deleted in #1373
  • Encrypt/DecryptBlock were moved down from SymmetricCipher to BlockCipher in #1369
  • The previously nonfunctional ZlibStream was deleted and the API of Compressor was changed in #1326
  • SftpFileSytemInformation was renamed to SftpFileSystemInformation in #1425
  • See the full API diff at the end

What's Changed

New Contributors

Full Changelog: 2024.0.0...2024.1.0

API diff
namespace Renci.SshNet
{
     public abstract class BaseClient : Renci.SshNet.IBaseClient, System.IDisposable
     {
-        public bool IsConnected { get; }
+        public virtual bool IsConnected { get; }
-        public event System.EventHandler<Renci.SshNet.Common.ExceptionEventArgs> ErrorOccurred;
+        public event System.EventHandler<Renci.SshNet.Common.ExceptionEventArgs>? ErrorOccurred;
-        public event System.EventHandler<Renci.SshNet.Common.HostKeyEventArgs> HostKeyReceived;
+        public event System.EventHandler<Renci.SshNet.Common.HostKeyEventArgs>? HostKeyReceived;
-        public event System.EventHandler<Renci.SshNet.Common.SshIdentificationEventArgs> ServerIdentificationReceived;
+        public event System.EventHandler<Renci.SshNet.Common.SshIdentificationEventArgs>? ServerIdentificationReceived;
     }

     public class CipherInfo
     {
-        public CipherInfo(int keySize, System.Func<byte[], byte[], Renci.SshNet.Security.Cryptography.Cipher> cipher) { }
+        public CipherInfo(int keySize, System.Func<byte[], byte[], Renci.SshNet.Security.Cryptography.Cipher> cipher, bool isAead = false) { }
+        public bool IsAead { get; }
     }

-    public class CommandAsyncResult : System.IAsyncResult
-    {
-        public object AsyncState { get; }
-        public System.Threading.WaitHandle AsyncWaitHandle { get; }
-        public int BytesReceived { get; set; }
-        public int BytesSent { get; set; }
-        public bool CompletedSynchronously { get; }
-        public bool IsCompleted { get; }
-    }

     public interface ISftpClient : Renci.SshNet.IBaseClient, System.IDisposable
     {
-        System.IAsyncResult BeginDownloadFile(string path, System.IO.Stream output, System.AsyncCallback asyncCallback);
+        System.IAsyncResult BeginDownloadFile(string path, System.IO.Stream output, System.AsyncCallback? asyncCallback);
-        System.IAsyncResult BeginListDirectory(string path, System.AsyncCallback asyncCallback, object state, System.Action<int> listCallback = null);
+        System.IAsyncResult BeginListDirectory(string path, System.AsyncCallback? asyncCallback, object? state, System.Action<int>? listCallb...
Read more

2024.0.0

Choose a tag to compare

@WojciechNagorski WojciechNagorski released this 21 Feb 19:20
a314700

New features:

  • ShellStream has been completely rewritten, all bugs fixed and performance improved.
  • Allow writing to stdin of SshCommand
  • Support for Trimming and AOT
  • Add new MAC algorithms:
    • hmac-md5-etm@openssh.com
    • hmac-md5-96-etm@openssh.com
    • hmac-sha1-etm@openssh.com
    • hmac-sha1-96-etm@openssh.com
    • hmac-sha2-256-etm@openssh.com
    • hmac-sha2-512-etm@openssh.com
  • Drop old MAC algorithms:
    • hmac-ripemd160
    • hmac-ripemd160@openssh.com

The list of changes:

New Contributors

Full Changelog: 2023.0.1...2024.0.0

2023.0.1

Choose a tag to compare

@WojciechNagorski WojciechNagorski released this 29 Dec 14:15
7436a38

New features:

  • Improve SFTP performance on medium/high latency connections
  • Use System.Security.Cryptography in AesCipher
  • Use hardware-accelerated AES
  • Add support for .NET 8.0
  • Reduces heap allocations
  • And many more.

The list of changes:

New Contributors

Full Changelog: 2023.0.0...2023.0.1

2023.0.0

Choose a tag to compare

@WojciechNagorski WojciechNagorski released this 10 Oct 19:26
1c7166a

New features:

  • Support for .NET 6, 7, and .NET Standard 2.1
  • Support for RSA-SHA256/512 signature algorithms
  • Support for parsing OpenSSH keys with ECDSA 256/384/521 and RSA
  • Support for SHA256 and MD5 fingerprints for host key validation
  • Added async support to SftpClient and SftpFileStream
  • Added ISftpFile interface to SftpFile
  • Removed support for old target frameworks
  • Improved performance and stability
  • Added the ability to set the last write and access time for Sftp files

The list of changes:

New Contributors

Thank you to all of our contributors for making SSH.NET the best SSH library for .NET!

Full Changelog: 2020.0.1...2023.0.0

API listing follows standard diff formatting.
Lines preceded by a '+' are additions and a '-' indicates removal.

Renci.SshNet

 namespace Renci.SshNet {
-    public abstract class BaseClient : IDisposable {
+    public abstract class BaseClient : IBaseClient, IDisposable {
+        public Task ConnectAsync(CancellationToken cancellationToken);
     }
+    public interface IBaseClient
+    public interface IPrivateKeySource
-    public interface ISftpClient {
+    public interface ISftpClient : IBaseClient, IDisposable {
+        Task DeleteFileAsync(string path, CancellationToken cancellationToken);
-        IEnumerable<SftpFile> EndListDirectory(IAsyncResult asyncResult);
+        IEnumerable<ISftpFile> EndListDirectory(IAsyncResult asyncResult);
-        SftpFile Get(string path);
+        ISftpFile Get(string path);
+        Task<SftpFileSytemInformation> GetStatusAsync(string path, CancellationToken cancellationToken);
-        IEnumerable<SftpFile> ListDirectory(string path, Action<int> listCallback = null);
+        IEnumerable<ISftpFile> ListDirectory(string path, Action<int> listCallback = null);
+        IAsyncEnumerable<ISftpFile> ListDirectoryAsync(string path, CancellationToken cancellationToken);
+        Task<SftpFileStream> OpenAsync(string path, FileMode mode, FileAccess access, CancellationToken cancellationToken);
+        Task RenameFileAsync(string oldPath, string newPath, CancellationToken cancellationToken);
+        void SetLastAccessTime(string path, DateTime lastAccessTime);
+        void SetLastAccessTimeUtc(string path, DateTime lastAccessTimeUtc);
+        void SetLastWriteTime(string path, DateTime lastWriteTime);
+        void SetLastWriteTimeUtc(string path, DateTime lastWriteTimeUtc);
     }
     public class NetConfClient : BaseClient {
+        public NetConfClient(string host, int port, string username, params IPrivateKeySource[] keyFiles);
-        public NetConfClient(string host, int port, string username, params PrivateKeyFile[] keyFiles);
+        public NetConfClient(string host, string username, params IPrivateKeySource[] keyFiles);
-        public NetConfClient(string host, string username, params PrivateKeyFile[] keyFiles);
     }
     public class PrivateKeyAuthenticationMethod : AuthenticationMethod, IDisposable {
+        public PrivateKeyAuthenticationMethod(string username, params IPrivateKeySource[] keyFiles);
-        public PrivateKeyAuthenticationMethod(string username, params PrivateKeyFile[] keyFiles);
-        public ICollection<PrivateKeyFile> KeyFiles { get; private set; }
+        public ICollection<IPrivateKeySource> KeyFiles { get; private set; }
     }
     public class PrivateKeyConnectionInfo : ConnectionInfo, IDisposable {
+        public PrivateKeyConnectionInfo(string host, int port, string username, params IPrivateKeySource[] keyFiles);
-        public PrivateKeyConnectionInfo(string host, int port, string username, params PrivateKeyFile[] keyFiles);
+        public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params IPrivateKeySource[] keyFiles);
-        public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params PrivateKeyFile[] keyFiles);
+        public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params IPrivateKeySource[] keyFiles);
-        public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, st...
Read more

2020.0.2

Choose a tag to compare

@drieseng drieseng released this 29 May 14:53

This release fixes a security vulnerability in our X25519 key exchange that could allow an attacker to eavesdrop the
communications to decrypt them.

More information is available in advisory CVE-2022-29245.

2020.0.1

Choose a tag to compare

@drieseng drieseng released this 24 Jan 14:07

Fixes

General

  • Support LF as line ending for banner and identification string

    Even though RFC 4253 requires that an identification string MUST be terminated by a carriage return and line feed, this fix restores support for banners and identification strings that are only terminated by a line feed.
    This is a workaround for an issue in version 7.4 of OpenSSH which was fixed in version 7.5.

    Fixes issue #761.

Feedback

Target framework support

While our list of supported target frameworks is impressive, it does come with a cost. Some of these target frameworks are no longer supported by Microsoft and even required software that is no longer available for download.

We'd like to gather feedback from our users through this issue to learn how important it is to continue supporting all these target frameworks.

Twitter

Do you want to keep track of general progress and annoucements for SSH.NET? You can now follow us on Twitter.

Supporting SSH.NET

Do you or your company rely on SSH.NET in your projects? If you want to encourage us to keep on going and show us that you appreciate our work, please consider becoming a sponsor through GitHub Sponsors.