Releases: sshnet/SSH.NET
2024.2.0
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
andzlib@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 withSystem.Numerics.BigInteger
in #1469Renci.SshNet.Common.DerData
andRenci.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
- Make ZlibOpenSsh public by @Rob-Hague in #1433
- Docs updates by @Rob-Hague in #1432
- Ref System.Memory for net462 and netstandard2.0 by @scott-xu in #1417
- Remove some #ifdefs with System.Memory by @Rob-Hague in #1434
- Allow empty softwareversion string (#822) by @doerig in #1441
- .NET 9: don't treat NuGet audit Warnings as Errors and fix warning by @mus65 in #1443
- Stabilise some more tests by @Rob-Hague in #1438
- Replace internal BouncyCastle with NuGet package by @mus65 in #1370
- Drop legacy algorithms part 1 by @Rob-Hague in #1442
- Clean up Abstractions / use HashData by @mus65 in #1451
- [Curve25519] Use BouncyCastle instead of Chaos.NaCl by @scott-xu in #1447
- [Ed25519] Use BouncyCastle instead of Chaos.NaCl by @scott-xu in #1448
- Remove Chaos.Nacl by @scott-xu in #1455
- [Zlib] Falls back to use BouncyCastle if BCL doesn't support by @scott-xu in #1453
- Add support for AEAD ChaCha20Poly1305 Cipher by @scott-xu in #1416
- Integrate with Nerdbank.GitVersioning by @scott-xu in #1299
- Use BCL ECDiffieHellman for KeyExchange instead of BouncyCastle (.NET 8.0 onward only) by @scott-xu in #1371
- Enable all net48 integration tests and stabilise tests by @scott-xu in #1456
- Revert mono/.NET Framework integration tests by @Rob-Hague in #1462
- Add another allowed SocketError value in tests by @Rob-Hague in #1457
- Use System.Security.Cryptography for DSA by @Rob-Hague in #1458
- Use ExceptionDispatchInfo to retain call stack in AsyncResult.EndInvoke() by @scott-xu in #1470
- Port shared tests folder by @Rob-Hague in #1467
- [AesGcm] Falls back to use BouncyCastle if BCL doesn't support by @scott-xu in #1450
- another .NET 9 SDK Build fix by @mus65 in #1475
- [ECDsa] Falls back to use BouncyCastle if BCL (Mono) doesn't support by @scott-xu in #1461
- Use System.Numerics.BigInteger by @Rob-Hague in #1469
- Remove unnecessary finalizers by @Rob-Hague in #1209
- fix "client not connected" after SFTP reconnect by @mus65 in #1484
- [Private Key] Support more ciphers for OpenSSH private key decryption by @scott-xu in #1487
- Migrate to NuGet Central Package Management by @mus65 in #1488
- Ref System.Formats.Asn1 nuget package by @scott-xu in #1490
- Update dependencies by @mus65 in #1492
- Miscellaneous cleanup/throw helpers by @Rob-Hague in #1491
- Update SonarAnalyzer.CSharp by @mus65 in #1494
- Add support for OpenSSL PKCS#8 private key format by @scott-xu in #1496
- Add interface to SshClient by @eugencowie in #1499
- Added ExistsAsync and GetAsync to SftpClient by @snargledorf in #1501
- fix ConnectAsync not respecting the connection timeout by @mus65 in #1502
- Added ChangeDirectoryAsync to SftpClient by @snargledorf in #1504
- Added CreateDirectoryAsync to SftpClient by @snargledorf in #1505
- Added support for deleting directories asynchronously by @snargledorf in #1503
- Fix sftp async methods not observing error conditions by @Rob-Hague in #1510
- Add support for OpenSSH certificates by @Rob-Hague in #1498
- Swallow ObjectDisposed on SFTP wait handle when receiving late response by @Rob-Hague in #1531
- Bump test dependencies by @Rob-Hague in #1532
New Contributors
- @doerig made their first contribution in #1441
- @eugencowie made their first contribution in #1499
- @snargledorf made their first contribution in #1501
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 : ...
2024.1.0
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 returningint
to returningint?
to reflect the fact that an exit status may not always be returned.PipeStream
(which provides the implementation ofSshCommand.OutputStream
andExtendedOutputStream
) 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
andMaxBufferLength
have been removed.
CommandAsyncResult
was deleted in #1426RsaCipher
,AsymmetricCipher
andCipherDigitalSignature
were deleted in #1373Encrypt/DecryptBlock
were moved down fromSymmetricCipher
toBlockCipher
in #1369- The previously nonfunctional
ZlibStream
was deleted and the API ofCompressor
was changed in #1326 SftpFileSytemInformation
was renamed toSftpFileSystemInformation
in #1425- See the full API diff at the end
What's Changed
- Fix ShellStream when receiving data larger than buffer length by @Rob-Hague in #1337
- fix link to tests in README by @mus65 in #1338
- Remove feature binary serialization by @scott-xu in #1325
- Changed Private Key Regex to be more tolerant regarding new lines at end of key file by @staecthSICKAG in #1344
- Use latest .NET 8 SDK in Ubuntu build by @Rob-Hague in #1352
- Use BCL Timeout by @scott-xu in #1353
- Fix CancelAsync Cause Deadlock by @zeotuan in #1345
- Cleanup and muting of analyzer warnings by @jscarle in #1357
- SftpClient: handle the SFTP session being closed by the server by @mus65 in #1362
- Handle unknown channel messages correctly by @mus65 in #1363
- Remove enormous array allocations in tests causing instability in CI by @Rob-Hague in #1367
- Add Rob-Hague to CODEOWNERS by @WojciechNagorski in #1376
- enable nullable on BaseClient and SftpClient by @mus65 in #1339
- Added support for GitHub pages using docfx by @jscarle in #1358
- Add support for Zlib compression (.NET 6.0 onward only) by @scott-xu in #1326
- git: checkout cs files with crlf by @mus65 in #1372
- Fix nullable error in build by @Rob-Hague in #1377
- Add support for AEAD AES 128/256 GCM Ciphers (.NET 6.0 onward only) by @scott-xu in #1369
- Add an AOT compatibility test app by @Rob-Hague in #1378
- Implement OpenSSH strict key exchange extension by @scott-xu in #1366
- Fix potential side-channel timing attack issue by @scott-xu in #1375
- Handle timeout correctly on Socks5 Proxy by @BoronBGP in #1342
- Fix ArgumentException usage in BlockCipher by @IgorMilavec in #818
- Fix SocketAsyncEventArgsAwaitable calling continuation multiple times by @IgorMilavec in #918
- gitattributes: set diff=csharp on cs files by @mus65 in #1393
- drop obsolete #if directives by @mus65 in #1394
- Use System.Security.Cryptography for RSA by @Rob-Hague in #1373
- Tweak AsyncSocketListener in tests by @Rob-Hague in #1382
- Documentation updates by @Rob-Hague in #1395
- Cleanup formatting and style and enforce it in CI by @mus65 in #1380
- fix flaky Connectivity Tests by @mus65 in #1403
- fix flaky ReceiveOnServerSocketShouldReturnZero test by @mus65 in #1404
- fix flaky Sftp_BeginUploadFile test by @mus65 in #1402
- More AsyncSocketListener patchwork by @Rob-Hague in #1408
- use Regex Source Generator for .NET 7+ by @mus65 in #1401
- Enable nullable on NetConf/Scp/SshClient by @mus65 in #1392
- make ConnectShouldActivateKeepAliveIfSessionIs test less flaky by @mus65 in #1410
- Delete CountdownEventTests by @Rob-Hague in #1409
- dotnet pack in CI by @Rob-Hague in #1400
- Relax the RSA/DSA decision for SSH2 keys by @Rob-Hague in #1190
- Fix a few issues with PipeStream by @Rob-Hague in #1399
- fix flaky SFTP file time tests by @mus65 in #1414
- doc: Update examples.md by @lupaulus in #1421
- A couple of changes/fixes in SshCommand by @Rob-Hague in #1423
- Rename SftpFileSytemInformation to SftpFileSystemInformation by @fndejan in #1425
- Support creating Shell(Stream) without PTY by @scott-xu in #1419
- fix build with .NET 9.0 SDK by @mus65 in #1427
- Updated NETCONF framing protocol detection to check both client & server capabilities by @declspec in #639
- Fix netconf framing protocol by @schaveyt in #946
- On SOCKS5 proxy: set hostname, not always IP by @jjvaca in #1072
- Remove unnecessary DNS lookup in Connect by @Rob-Hague in #1412
- Add SshCommand.ExecuteAsync by @Rob-Hague in #1426
- Set version to 2024.1.0 by @Rob-Hague in #1429
New Contributors
- @staecthSICKAG made their first contribution in #1344
- @zeotuan made their first contribution in #1345
- @BoronBGP made their first contribution in #1342
- @lupaulus made their first contribution in #1421
- @fndejan made their first contribution in #1425
- @declspec made their first contribution in #639
- @schaveyt made their first contribution in #946
- @jjvaca made their first contribution in #1072
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...
2024.0.0
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:
- Require Microsoft.Bcl.AsyncInterfaces >=1.0.0 instead of =8.0.0 by @mus65 in #1288
- Remove unneeded feature flags and pass cancellationToken to DNS request by @mus65 in #1290
- Plumbing for more async/await work by @jacobslusser in #1281
- Fix build script by @WojciechNagorski in #1295
- Enable trim analysis and fix warnings by @Rob-Hague in #1216
- Integration benchmark tests by @WojciechNagorski in #1298
- Merge nuspec and CommonAssemblyInfo into csproj by @scott-xu in #1256
- Update gitignore by @Rob-Hague in #1261
- Use BinaryPrimitives in Pack by @Rob-Hague in #1305
- Tweak semaphore usage in Session by @Rob-Hague in #1304
- Allow the integration tests to run on .NET Framework by @Rob-Hague in #1286
- Added SshCommand.InputStream to allow writing to stdin of SshCommand by @realvizu in #1293
- Add tests and benchmarks for ShellStream.Read and Expect by @Rob-Hague in #1313
- 2023.0.2 version by @WojciechNagorski in #1314
- Improve ShellStream Expect by @WojciechNagorski in #1315
- No need to collect nuget packages in appveyor.yml as the packages are not generated when build by @scott-xu in #1317
- Significantly improve performance of ShellStream's Expect methods by @jscarle in #1207
- Fixed dequeuing of incoming queue by @jscarle in #1319
- Support ETM (Encrypt-then-MAC) variants for HMAC by @scott-xu in #1316
- CI: remove install of net8.0 sdk on VS image by @Rob-Hague in #1323
- Fix a few issues with ShellStream by @Rob-Hague in #1322
- Drop RIPEMD160 by @scott-xu in #1324
- Restore the write buffer to ShellStream by @Rob-Hague in #1327
- Limit TimeSpan timeouts to Int32 MaxValue by @jscarle in #1321
- Updated dependencies. by @jscarle in #1328
- Moved IDE0005 warning configuration. by @jscarle in #1329
- Version 2024.0.0 by @WojciechNagorski in #1330
- Add
Closed
event toShellStream
. by @scott-xu in #1332 - Microsoft.Bcl.AsyncInterfaces version >= 1.0.0 by @WojciechNagorski in #1334
New Contributors
Full Changelog: 2023.0.1...2024.0.0
2023.0.1
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:
- Enable list directory async for net framework by @Patrick-3000 in #1206
- Remove placeholder tests by @Rob-Hague in #1183
- Move test projects by @WojciechNagorski in #1212
- Delete more dummy tests by @Rob-Hague in #1213
- Update Nugets 10/2023 by @WojciechNagorski in #1214
- Upgrade .NET SDK from 7.402 to 7.403. by @drieseng in #1222
- Merge partial classes and complete IForwardedPort interface by @drieseng in #1223
- Fix analyzer errors in Renci.SshNet and Renci.SshNet.TestTools.OpenSSH by @drieseng in #1229
- Increase test coverage for AesCipher by @Rob-Hague in #1232
- Use shared Data folder for client keys in integration tests by @Rob-Hague in #1219
- Use CollectionAssert in ListDirectory tests by @Rob-Hague in #1166
- Improve SFTP performance on medium/high latency connections by @zybexXL in #866
- Update global.json by @Rob-Hague in #1240
- Tweak diagnostics by @Rob-Hague in #1241
- Use System.Security.Cryptography in AesCipher by @Rob-Hague in #1235
- Enable trace logging for Integration tests by @WojciechNagorski in #1242
- Expose SshIdentificationReceived event by @scott-xu in #1195
- Fix avoidable exception when data length is too long by @se006 in #823
- Fix build break in Release by @Rob-Hague in #1248
- Use hardware-accelerated AES CryptoServiceProvider by @zybexXL in #865
- Disable a few duplicate analyzer rules by @drieseng in #1254
- Test integration tests by @WojciechNagorski in #1250
- Add support for .NET 8.0 by @scott-xu in #1255
- Fail with a friendlier error message when response has not been set by @Rob-Hague in #1245
- Disable some impactful analyzers by @Rob-Hague in #1246
- Rebased AsyncResult fix by @Rob-Hague in #1184
- Standardizes additional file types in .editorconfig by @jacobslusser in #1266
- Replace SemaphoreLight with SemaphoreSlim by @Rob-Hague in #1265
- Always use factories for HmacAlgorithms by @Rob-Hague in #1262
- Native async by @WojciechNagorski in #1267
- Removes MessageAttribute in favor of properties on Message class by @jacobslusser in #1270
- Reduces heap allocations for the some byte[] uses by @jacobslusser in #1272
- Maintain current build solution by @scott-xu in #1268
- Send the client key exchange init in Connect by @Rob-Hague in #1274
- Add a few spans on net6.0 or greater by @Rob-Hague in #1138
- Make keys immutable by @Rob-Hague in #1264
- Try to stabilise a few tests by @Rob-Hague in #1278
- Fix #1275. Hung Dispose() caused by infinite socket timeout by @jkillingsworth in #1280
- Authenticate with ssh-rsa by default by @Rob-Hague in #1283
- Upgrade packages by @Rob-Hague in #1279
- Remove code examples by @WojciechNagorski in #1210
New Contributors
- @Patrick-3000 made their first contribution in #1206
- @scott-xu made their first contribution in #1195
- @se006 made their first contribution in #823
- @jacobslusser made their first contribution in #1266
- @jkillingsworth made their first contribution in #1280
Full Changelog: 2023.0.0...2023.0.1
2023.0.0
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
andSftpFileStream
- Added
ISftpFile
interface toSftpFile
- 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:
- Assets/logos by @Filini in #782
- OPENSSH KeyReader for more keys by @darinkes in #614
- Add interface to SftpFile #120 by @wxtsxt in #812
- Start MessageListener with ThreadAbstraction.ExecuteThreadLongRunning #2 by @IgorMilavec in #902
- Add async support to SftpClient and SftpFileStream by @IgorMilavec in #819
- Fix virus false-positive by Defender on Renci.SSHNet.Tests.dll by @zybexXL in #867
- Add unit tests for task-based asynchronous API by @IgorMilavec in #906
- correct 'Documenation' to 'Documentation' by @maxijabase in #838
- Agent auth and Keygen by @darinkes in #794
- Add IBaseClient for BaseClient and ISftpClient to inherit from by @Owen-Krueger in #975
- Fix typo by @psh9508 in #999
- Fix Seek Operations in SftpFileStream by @lemonyte in #910
- Add back copyright to license by @drieseng in #1060
- Removing old target frameworks by @WojciechNagorski in #1109
- Remove old features [Part 1] by @WojciechNagorski in #1117
- Remove FEATURE_DIRECTORYINFO_ENUMERATEFILES by @WojciechNagorski in #1119
- Fix some (lots of) issues reported by analyzers. by @drieseng in #1125
- Round 2 of analyzer fixes and general cleanup. by @drieseng in #1132
- Analyzer fixes round 3. by @drieseng in #1135
- Replace Array.Empty with Array.Empty() by @Rob-Hague in #1137
- Replace IsNullOrWhiteSpace extension by @Rob-Hague in #1142
- Use License Expression for NuGet Package by @mus65 in #1146
- MSTest Integration tests by @WojciechNagorski in #1148
- ListDirectoryAsync return IAsyncEnumerable by @WojciechNagorski in #1126
- Fix the assembly resolution build warning by @Rob-Hague in #1165
- Delete performance/longrunning tests by @Rob-Hague in #1143
- Move Integration tests by @WojciechNagorski in #1173
- Add a benchmarks project by @Rob-Hague in #1151
- Use ExceptionDispatchInfo to retain call stack in Session.WaitOnHandle() by @IgorMilavec in #936
- Support SHA256 fingerprints for host key validation by @DavisNT in #1098
- Add support for RSA SHA-2 public key algorithms by @Rob-Hague in #1177
- Improvements after #1177 by @WojciechNagorski in #1180
- Use ExceptionDispatchInfo in more places by @Rob-Hague in #1182
- Try to "fix" the flaky test by @Rob-Hague in #1185
- Enable DSA tests by @Rob-Hague in #1181
- FingerPrints improvements by @WojciechNagorski in #1186
- Use OS-agnostic socket error codes to allow tests run on different OSes by @dimhotepus in #1179
- Fix for channel session semaphore from thread blocking by @patrick-yates-redgate in #1071
- Update ISftpClient by @WojciechNagorski in #1193
- Implement set last write and access time by @WojciechNagorski in #1194
- Add/migrate hmac+cipher integration tests by @Rob-Hague in #1189
- Improve tests for (Get|Set)LastAccessTime(Utc) by @drieseng in #1198
New Contributors
- @wxtsxt made their first contribution in #812
- @IgorMilavec made their first contribution in #902
- @zybexXL made their first contribution in #867
- @maxijabase made their first contribution in #838
- @Owen-Krueger made their first contribution in #975
- @psh9508 made their first contribution in #999
- @lemonyte made their first contribution in #910
- @WojciechNagorski made their first contribution in #1109
- @Rob-Hague made their first contribution in #1137
- @mus65 made their first contribution in #1146
- @DavisNT made their first contribution in #1098
- @dimhotepus made their first contribution in #1179
- @patrick-yates-redgate made their first contribution in #1071
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...
2020.0.2
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
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.
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.
2020.0.0
Changes
Target framework support
This release of SSH.NET adds support for .NET Standard 2.0.
This brings the full list of the supported target frameworks to:
- .NET Framework 3.5
- .NET Framework 4.0 (and higher)
- .NET Standard 1.3
- .NET Standard 2.0
- Silverlight 4
- Silverlight 5
- Windows Phone 7.1
- Windows Phone 8.0
- Universal Windows Platform 10
Fixes issue #357, #436 and #474.
Key exchange algorithms
SSH.NET now supports the following additional key exchange algorithms:
- curve25519-sha256
- curve25519-sha256@libssh.org
- ecdh-sha2-nistp256
- ecdh-sha2-nistp384
- ecdh-sha2-nistp521
- diffie-hellman-group14-sha256
- diffie-hellman-group16-sha512
Fixes issue #53, #406 and #504.
Host key algorithms
The following additional host key algorithms are now supported:
- ssh-ed25519
- ecdsa-sha2-nistp256
- ecdsa-sha2-nistp384
- ecdsa-sha2-nistp521
Public key authentication
SSH.NET now supports the following private key formats:
- RSA in OpenSSL PEM and ssh.com format
- DSA in OpenSSL PEM and ssh.com format
- ECDSA 256/384/521 in OpenSSL PEM format
- ED25519 in OpenSSH key format
Fixes issue #485.
Troubleshooting
Until now any issue related to Protocol Version Exchange would be reported using a single message:
Server response does not contain SSH protocol identification.
As of this release, we identify - and report - three distinct issues:
-
The server immediately closed the connections upon reception of our SSH identification string.
The server response does not contain an SSH identification string. The connection to the remote server was closed before any data was received. More information on the Protocol Version Exchange is available here: https://tools.ietf.org/html/rfc4253#section-4.2
-
The identification string of the server contains a null character (which is prohibited).
The server response contains a null character at position 0x00000005: 00000000 ED 95 9C 21 00 ...!. A server must not send a null character before the Protocol Version Exchange is complete. More information is available here: https://tools.ietf.org/html/rfc4253#section-4.2
-
The server response does not contain an SSH identification string.
The server response does not contain an SSH identification string: 00000000 48 54 54 50 2F 31 2E 30 20 32 30 30 20 4F 4B 0D HTTP/1.0 200 OK. 00000010 0A 43 6F 6E 74 65 6E 74 2D 4C 65 6E 67 74 68 3A .Content-Length: 00000020 20 31 30 0D 0A 43 6F 6E 74 65 6E 74 2D 54 79 70 10..Content-Typ 00000030 65 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 6F e: application/o 00000040 63 74 65 74 2D 73 74 72 65 61 6D 0D 0A ctet-stream.. More information on the Protocol Version Exchange is available here: https://tools.ietf.org/html/rfc4253#section-4.2
Channel close timeout
A ChannelCloseTimeout property has been introduced on ConnectionInfo that controls the timeout to apply when waiting for a server to acknowledge closing a channel. The default value is 1 second.
If a server does not report to our SSH_MSG_CHANNEL_CLOSE message with a SSH_MSG_CHANNEL_CLOSE message before the specified timeout elapses, we'll stop waiting and consider the channel to be closed.
Fixes issue #335.
SftpClient
- SftpClient now implements ISftpClient to allow for each testing (issue #193).
Breaking changes
ScpClient
CVE-2018-20685 caused OpenSSH to implement more strict validation of file paths. ScpClient was updated to correctly deal with these changes.
In case of a recursive directory upload, ScpClient cannot fully absorb the impact of these changes and as such Upload(DirectoryInfo directoryInfo, string path)
now fails if path does not exist on the remote host. For the same reason, the mode and modification/access time will also no longer be set on path.
The mode and modification/access time continue to be set on any files or subdirectories that are uploaded.
Fixes
General
- Use big endian byte order for port number in SOCKS request (issue #125 and #447).
Connect()
times out when server rejects initializing subsystem (issue #308).- Keep-alives are not activated if connection is already opened (issue #334).
- Connection cannot be re-established when subsystem cannot be executed (issue #338).
- Closed event on Channel is not deterministic (issue #319).
Disconnect()
andDispose()
may block indefinitely on .NET Core (issue #355 and #686).- EAP implementation does not correctly deal with a socket operation that is completed synchronously (issue #377 and #571).
- Identification string is not immediately sent when connection is established (issue #689 and #505).
- Minor protocol version parsing bug (issue #749).
SftpClient
- Fix UTC time handling in case of DST shifts (issue #356)
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.
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.
Thanks
This release wouldn't have been possible without contributions from:
@darinkes, @AtosNicoS, @dancret, @menees, @ericbrumfield
Special thanks for @Filini producing our new logo assets!
2020.0.0-beta1
Changes
Target framework support
This release of SSH.NET adds support for .NET Standard 2.0.
This brings the full list of the supported target frameworks to:
- .NET Framework 3.5
- .NET Framework 4.0 (and higher)
- .NET Standard 1.3
- .NET Standard 2.0
- Silverlight 4
- Silverlight 5
- Windows Phone 7.1
- Windows Phone 8.0
- Universal Windows Platform 10
Fixes issue #357, #436 and #474.
Key exchange algorithms
SSH.NET now supports the following additional key exchange algorithms:
- curve25519-sha256
- curve25519-sha256@libssh.org
- ecdh-sha2-nistp256
- ecdh-sha2-nistp384
- ecdh-sha2-nistp521
- diffie-hellman-group14-sha256
- diffie-hellman-group16-sha512
Fixes issue #53, #406 and #504.
Host key algorithms
The following additional host key algorithms are now supported:
- ssh-ed25519
- ecdsa-sha2-nistp256
- ecdsa-sha2-nistp384
- ecdsa-sha2-nistp521
Public key authentication
SSH.NET now supports the following private key formats:
- RSA in OpenSSL PEM and ssh.com format
- DSA in OpenSSL PEM and ssh.com format
- ECDSA 256/384/521 in OpenSSL PEM format
- ED25519 in OpenSSH key format
Fixes issue #485.
Channel close timeout
A ChannelCloseTimeout property has been introduced on ConnectionInfo that controls the timeout to apply when waiting for a server to acknowledge closing a channel. The default value is 1 second.
If a server does not report to our SSH_MSG_CHANNEL_CLOSE message with a SSH_MSG_CHANNEL_CLOSE message before the specified timeout elapses, we'll stop waiting and consider the channel to be closed.
Fixes issue #335.
Breaking changes
ScpClient
CVE-2018-20685 caused OpenSSH to implement more strict validation of file paths. ScpClient was updated to correctly deal with these changes.
In case of a recursive directory upload, ScpClient cannot fully absorb the impact of these changes and as such Upload(DirectoryInfo directoryInfo, string path)
now fails if path does not exist on the remote host. For the same reason, the mode and modification/access time will also no longer be set on path.
The mode and modification/access time continue to be set on any files or subdirectories that are uploaded.
Fixes
General
- Use big endian byte order for port number in SOCKS request (issue #125 and #447).
Connect()
times out when server rejects initializing subsystem (issue #308).- Keep-alives are not activated if connection is already opened (issue #334).
- Connection cannot be re-established when subsystem cannot be executed (issue #338).
- Closed event on Channel is not deterministic (issue #319).
Disconnect()
andDispose()
may block indefinitely on .NET Core (issue #355 and #686).- EAP implementation does not correctly deal with a socket operation that is completed synchronously (issue #377 and #571).
- Identification string is not immediately sent when connection is established (issue #689 and #505).
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.
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.
Thanks
This release wouldn't have been possible without contributions from:
@darinkes, @AtosNicoS, @dancret
2016.1.0
Changes
Distribution
The NuGet Package Manager in Visual Studio 2012 does not support packages in which a given dependency is defined for more than one TFM. Since a fix for this issue is not expected any time soon, we're reviving support for a binary distribution.
This plain .zip file contains the SSH.NET assembly, and where applicable any dependencies, for all supported target frameworks.
For Visual Studio 2015 and higher, the SSH.NET NuGet package remains our primary distribution mechanism.
General
- Increase initial window size for SSH channels from 2 MB to 2147483647 (2^31 - 1) bytes. This results in less protocol overhead when receiving data from a SSH server.
- Data of an SSH_MSG_IGNORE server request is now ignored when the specified length is greater than the actual available bytes (issue #41).
- Reduce overhead when invoking both
Disconnect()
andDispose()
. - Improve performance of SSH message processing by eliminating use of dynamic dispatching.
ScpClient
A RemotePathTransformation property has been added to ScpClient that can be used to change if and how a remote path is transformed before it is passed to the scp command on the remote server.
SSH.NET comes with the following path transformations that are exposed through the RemotePathTransformation class (in Renci.SshNet):
-
DoubleQuote
Encloses a path in double quotes, and escapes any embedded double quote with a backslash.
This is the default, as it works fine with most SCP servers. -
ShellQuote
Quotes a path in a way to be suitable to be used with a shell-based SCP server.
This is the preferred mechanism for shell-based SCP servers, which typically means all Unix-like systems. -
None
Performs no transformation to the path.
This is the recommended transformation when the remote host does not require any quoting to preserve the literal value of metacharacters, or when remote paths are guaranteed not to contain such characters.
When none of the built-in transformations match the specific requirements of a remote host, a custom transformation can be supplied.
More information on this change is available here.
Example:
Download a file using SCP, and apply shell quoting to the remote path:
using Renci.SshNet;
public class Program
{
static void Main()
{
using (var client = new ScpClient("HOST", 22, "USER", "PWD"))
{
client.RemotePathTransformation = RemotePathTransformation.ShellQuote;
client.Connect();
using (var ms = new MemoryStream())
{
client.Download("/home/sshnet/file 123", ms);
}
}
}
}
Since we've configured ScpClient to use the ShellQuote transformation, the /home/sshnet/file 123
path
will automatically be enclosed in single quotes.
The actual path that is passed to the scp command on the remote host is therefore '/home/sshnet/file 123'
.
SftpClient
- When the read buffer is empty,
SftpFileStream.Read(byte[], int, int)
only writes those bytes to the buffer that go beyond the number of bytes requested by the caller. - Reduced memory allocations in SftpFileStream by lazily allocating read and write buffer.
- Improved compatibility of
SftpFileStream.SetLength(long value)
with System.IO.FileStream (PR #272):- Flush buffers before changing the length of stream.
- Move the current position to the last byte of the stream if the current position is greater than the new length.
- Eliminated extra read from server in SftpFileStream to determine EOF.
- Greatly improved performance of
SftpClient.(Begin)DownloadFile(...)
by asynchronously reading ahead chunks (issue #145 and #100).
SshClient
- A ForwardedPortDynamic now supports domain name addresses for SOCKS5 requests (issue #98).
Breaking changes
ScpClient
The Upload(FileInfo fileInfo, String path)
method in ScpClient now expects path to be the remote path of the file to which you want to upload, and throws a ScpException if a directory exists on the remote host for that path (issue #286).
Up until now, uploading a file with a given (remote) path could lead a different result depending on whether a directory for that path exits on the remote host.
Example:
using (var client = new ScpClient("host", "user", "pwd"))
{
client.Connect();
client.Upload(new FileInfo(@"c:\temp\newlog.txt", "/home/sshnet/log");
}
As of version 2016.1.0-beta 3 a ScpException will be thrown when /home/sshnet/log exists as a directory on the remote host.
In previous versions of SSH.NET this code would actually upload the content of the c:\temp\newlog.txt file to /home/sshnet/log/newlog.txt.
When /home/sshnet/log exists on the remote host as a file or does not exist at all, the content of the c:\temp\newlog.txt file will be uploaded to /home/sshnet/log. This has not changed.
SftpClient
-
The IsAsync property was removed from SftpFileStream. Previously this property always returned false.
-
The read and write position in SftpFileStream are no longer tracked separately. Reading from or seeking in the SftpFileStream will now also affect the position at which a subsequent write is performed, and vice versa (issue #253).
For example, the following code snippet will now write "123456" to the console:
var buffer = Encoding.UTF8.GetBytes("123456"); using (var client = new SftpClient("host", "user", "pwd")) { client.Connect(); using (var ws = client.OpenWrite(path)) { ws.Write(buffer, 0, 3); } using (var ws = client.OpenWrite(path)) { ws.Seek(3, SeekOrigin.Begin); ws.Write(buffer, 3, 3); } Console.WriteLine(client.ReadAllText(path, Encoding.UTF8)); }
-
To improve compatibility of SftpFileStream with System.IO.FileStream, Append mode is now only allowed when combined with write-only access (issue #267). This only affects
SftpClient.Open(string path, FileMode mode, FileAccess access)
.The following code snippet will now throw an ArgumentException:
using (var client = new SftpClient("host", "user", "pwd")) { client.Connect(); using (var fs = client.Open("/home/user/file.log", FileMode.Append, FileShare.Read)) { } }
Result:
System.ArgumentException: Append mode can be requested only when combined with write-only access. -
To improve compatibility of SftpClient with System.IO.File, the following methods now use UTF-8 encoding without a Byte-Order Mark (BOM):
void AppendAllLines(string path, IEnumerable<string> contents)
void AppendAllText(string path, string contents)
StreamWriter AppendText(string path)
StreamWriter CreateText(string path)
void WriteAllLines(string path, IEnumerable<string> contents)
void WriteAllLines(string path, string[] contents)
void WriteAllText(string path, string contents)
Fixes
General
-
Servers that do not implement RFC 4252 correctly may lead to stack overflow (issue #306).
Section 5.1 of the aforementioned RFC states the following on SSH_MSG_USERAUTH_FAILURE response:
The value of 'partial success' MUST be TRUE if the authentication request to which this is a response was successful. It MUST be FALSE if the request was not successfully processed.
Some SSH servers set 'partial success' to TRUE even if the authentication request was not processed successfully, and do not update the name-list to remove the method name that failed.
SSH.NET has now been updated only attempt authentication 5 times for a method that was considered partially successful.
If this limit is reached for a given method name, and no other authentication method is available, a SshAuthenticationException with message "Reached authentication attempt limit for method (<method name>)" will be thrown.
-
Key exchange is slow when size of group is more than 1024 bit (issue #304 and #130).
As part of the key exchange, SSH.NET sends a SSH_MSG_KEY_DH_GEX_REQUEST with a 1024 bit minimum and preferred group size, and 8192 bit maximum group size.
Before this fix, we would generate a private exponent that matches the size of the safe prime generated by the server. In some cases this meant using a 8192 bit private component to generate the client exchange value, which is a CPU intensive operation.
As from this fix, we generate a private exponent that is twice the hash size with a minimum of 1024 bit.
-
ConnectSocks5()
throws a ProxyException with a wrong message (issue #167). -
Comments in ProxyException.cs are not relevant (issue #163).
-
SSH exception after client connect using .NET 3.5 version (issue #113).
-
Handle leak when connection to SSH server fails (issue #55).
-
Race condition when both server and client close channel (issue #84).
-
Suppressing ...