mirror of
https://github.com/sshnet/SSH.NET.git
synced 2026-09-10 01:05:42 +00:00
Add .NET 10 target and make use of C#14 extension members (#1672)
* Add .NET 10 target * fix IDE0031 https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ide0031 * fix ca5399 https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca5399 * fix ca1515 https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1515 * fix ca2002 https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2002 * fix ca1508 new false positives. https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1508 * fix ca2000 https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2000 * fix ca2025 https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2025 * fix ca1849 https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1849 * fix Reverse() overloads because of https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/10.0/csharp-overload-resolution * supress CA2002 * Use extension members for ThrowHelpers * use extension members for CryptoAbstractions * use extension member for DateTime.UnixEpoch * use extension members for string.Join etc * use extension members for Convert.To/FromHexString * disable CA1508 * Update .NET 10 RC2 * Workaround Build Regression in .NET 10 RC2 https://github.com/dotnet/sdk/issues/51265 * suppress new warnings introduced by merge * Update to .NET 10 final release * Revert "Workaround Build Regression in .NET 10 RC2" This is fixed in the final release. This reverts commit5a59ac9aa8. * fix new warnings with MSTest 4 + .NET 10 * use same Randomizer instance * disable CA2000 * reduce CA1849 suppressions and disable duplicate S6966 * disable preview analyzers reverts6c3c06d95a
This commit is contained in:
+17
-1
@@ -177,7 +177,7 @@ dotnet_diagnostic.S2699.severity = none
|
||||
# S2930: "IDisposables" should be disposed
|
||||
# https://rules.sonarsource.com/csharp/RSPEC-2930/
|
||||
#
|
||||
# Duplicate of CA2000.
|
||||
# too noisy.
|
||||
dotnet_diagnostic.S2930.severity = none
|
||||
|
||||
# S2933: Fields that are only assigned in the constructor should be "readonly"
|
||||
@@ -344,6 +344,10 @@ dotnet_diagnostic.S5659.severity = none
|
||||
# https://rules.sonarsource.com/csharp/RSPEC-5773/
|
||||
dotnet_diagnostic.S4581.severity = none
|
||||
|
||||
# S6966: Awaitable method should be used
|
||||
# Duplicate of CA1849
|
||||
dotnet_diagnostic.S6966.severity = none
|
||||
|
||||
#### StyleCop rules ####
|
||||
|
||||
# SA1003: Symbols must be spaced correctly
|
||||
@@ -683,6 +687,10 @@ dotnet_diagnostic.CA1305.severity = none
|
||||
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1309
|
||||
dotnet_diagnostic.CA1309.severity = none
|
||||
|
||||
# CA1508: Avoid dead conditional code
|
||||
# Too many false positives.
|
||||
dotnet_diagnostic.CA1508.severity = none
|
||||
|
||||
# CA1510: Use ArgumentNullException throw helper
|
||||
#
|
||||
# This is only available in .NET 6.0 and higher. We'd need to use conditional compilation to only
|
||||
@@ -726,6 +734,14 @@ dotnet_diagnostic.CA1848.severity = silent
|
||||
# By default, this diagnostic is only reported for private members.
|
||||
dotnet_code_quality.CA1859.api_surface = private,internal
|
||||
|
||||
# CA1873: Evaluation of this argument may be expensive and unnecessary if logging is disabled
|
||||
dotnet_diagnostic.CA1873.severity = suggestion
|
||||
|
||||
# CA2000: Dispose objects before losing scope
|
||||
#
|
||||
# too noisy.
|
||||
dotnet_diagnostic.CA2000.severity = suggestion
|
||||
|
||||
# CA2208: Instantiate argument exceptions correctly
|
||||
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2208
|
||||
#
|
||||
|
||||
@@ -18,33 +18,33 @@ jobs:
|
||||
uses: actions/setup-dotnet@v5
|
||||
|
||||
- name: Build Unit Tests .NET
|
||||
run: dotnet build -f net9.0 test/Renci.SshNet.Tests/
|
||||
run: dotnet build -f net10.0 test/Renci.SshNet.Tests/
|
||||
|
||||
- name: Build IntegrationTests .NET
|
||||
run: dotnet build -f net9.0 test/Renci.SshNet.IntegrationTests/
|
||||
run: dotnet build -f net10.0 test/Renci.SshNet.IntegrationTests/
|
||||
|
||||
- name: Run Unit Tests .NET
|
||||
run: |
|
||||
dotnet test \
|
||||
-f net9.0 \
|
||||
-f net10.0 \
|
||||
--no-build \
|
||||
--logger "console;verbosity=normal" \
|
||||
--logger GitHubActions \
|
||||
-p:CollectCoverage=true \
|
||||
-p:CoverletOutputFormat=cobertura \
|
||||
-p:CoverletOutput=../../coverlet/linux_unit_test_net_9_coverage.xml \
|
||||
-p:CoverletOutput=../../coverlet/linux_unit_test_net_10_coverage.xml \
|
||||
test/Renci.SshNet.Tests/
|
||||
|
||||
- name: Run Integration Tests .NET
|
||||
run: |
|
||||
dotnet test \
|
||||
-f net9.0 \
|
||||
-f net10.0 \
|
||||
--no-build \
|
||||
--logger "console;verbosity=normal" \
|
||||
--logger GitHubActions \
|
||||
-p:CollectCoverage=true \
|
||||
-p:CoverletOutputFormat=cobertura \
|
||||
-p:CoverletOutput=../../coverlet/linux_integration_test_net_9_coverage.xml \
|
||||
-p:CoverletOutput=../../coverlet/linux_integration_test_net_10_coverage.xml \
|
||||
test/Renci.SshNet.IntegrationTests/
|
||||
|
||||
- name: Archive Coverlet Results
|
||||
@@ -82,13 +82,13 @@ jobs:
|
||||
- name: Run Unit Tests .NET
|
||||
run: |
|
||||
dotnet test `
|
||||
-f net9.0 `
|
||||
-f net10.0 `
|
||||
--no-build `
|
||||
--logger "console;verbosity=normal" `
|
||||
--logger GitHubActions `
|
||||
-p:CollectCoverage=true `
|
||||
-p:CoverletOutputFormat=cobertura `
|
||||
-p:CoverletOutput=../../coverlet/windows_unit_test_net_9_coverage.xml `
|
||||
-p:CoverletOutput=../../coverlet/windows_unit_test_net_10_coverage.xml `
|
||||
test/Renci.SshNet.Tests/
|
||||
|
||||
- name: Run Unit Tests .NET Framework
|
||||
@@ -173,7 +173,7 @@ jobs:
|
||||
- name: Run Integration Tests .NET
|
||||
run:
|
||||
dotnet test `
|
||||
-f net9.0 `
|
||||
-f net10.0 `
|
||||
--logger "console;verbosity=normal" `
|
||||
--logger GitHubActions `
|
||||
-p:CollectCoverage=true `
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||
<AnalysisLevel>preview-All</AnalysisLevel>
|
||||
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<!-- Should stay on LTS .NET releases. -->
|
||||
<PackageVersion Include="Microsoft.Bcl.Cryptography" Version="10.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.3" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="10.0.0" />
|
||||
<PackageVersion Include="MSTest" Version="4.0.2" />
|
||||
<PackageVersion Include="Moq" Version="4.20.72" />
|
||||
<PackageVersion Include="Nerdbank.GitVersioning" Version="3.7.115" />
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "9.0.300",
|
||||
"version": "10.0.100",
|
||||
"rollForward": "latestFeature"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
#nullable enable
|
||||
#if !NET
|
||||
using System.Text;
|
||||
#endif
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal static class ConvertExtensions
|
||||
{
|
||||
extension(Convert)
|
||||
{
|
||||
#if !NET
|
||||
public static byte[] FromHexString(string s)
|
||||
{
|
||||
return Org.BouncyCastle.Utilities.Encoders.Hex.Decode(s);
|
||||
}
|
||||
|
||||
public static string ToHexString(byte[] inArray)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(inArray);
|
||||
|
||||
var builder = new StringBuilder(inArray.Length * 2);
|
||||
|
||||
foreach (var b in inArray)
|
||||
{
|
||||
builder.Append(b.ToString("X2"));
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,80 +7,8 @@ namespace Renci.SshNet.Abstractions
|
||||
{
|
||||
internal static class CryptoAbstraction
|
||||
{
|
||||
private static readonly RandomNumberGenerator Randomizer = RandomNumberGenerator.Create();
|
||||
internal static readonly RandomNumberGenerator Randomizer = RandomNumberGenerator.Create();
|
||||
|
||||
internal static readonly SecureRandom SecureRandom = new SecureRandom(new CryptoApiRandomGenerator(Randomizer));
|
||||
|
||||
/// <summary>
|
||||
/// Generates a <see cref="byte"/> array of the specified length, and fills it with a
|
||||
/// cryptographically strong random sequence of values.
|
||||
/// </summary>
|
||||
/// <param name="length">The length of the array generate.</param>
|
||||
public static byte[] GenerateRandom(int length)
|
||||
{
|
||||
var random = new byte[length];
|
||||
Randomizer.GetBytes(random);
|
||||
return random;
|
||||
}
|
||||
|
||||
public static byte[] HashMD5(byte[] source)
|
||||
{
|
||||
#if NET
|
||||
return MD5.HashData(source);
|
||||
#else
|
||||
using (var md5 = MD5.Create())
|
||||
{
|
||||
return md5.ComputeHash(source);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static byte[] HashSHA1(byte[] source)
|
||||
{
|
||||
#if NET
|
||||
return SHA1.HashData(source);
|
||||
#else
|
||||
using (var sha1 = SHA1.Create())
|
||||
{
|
||||
return sha1.ComputeHash(source);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static byte[] HashSHA256(byte[] source)
|
||||
{
|
||||
#if NET
|
||||
return SHA256.HashData(source);
|
||||
#else
|
||||
using (var sha256 = SHA256.Create())
|
||||
{
|
||||
return sha256.ComputeHash(source);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static byte[] HashSHA384(byte[] source)
|
||||
{
|
||||
#if NET
|
||||
return SHA384.HashData(source);
|
||||
#else
|
||||
using (var sha384 = SHA384.Create())
|
||||
{
|
||||
return sha384.ComputeHash(source);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static byte[] HashSHA512(byte[] source)
|
||||
{
|
||||
#if NET
|
||||
return SHA512.HashData(source);
|
||||
#else
|
||||
using (var sha512 = SHA512.Create())
|
||||
{
|
||||
return sha512.ComputeHash(source);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#nullable enable
|
||||
namespace System
|
||||
{
|
||||
internal static class DateTimeExtensions
|
||||
{
|
||||
extension(DateTime)
|
||||
{
|
||||
#if !NET
|
||||
public static DateTime UnixEpoch
|
||||
{
|
||||
get
|
||||
{
|
||||
return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#nullable enable
|
||||
namespace System.Security.Cryptography
|
||||
{
|
||||
internal static class MD5Extensions
|
||||
{
|
||||
extension(MD5)
|
||||
{
|
||||
#if !NET
|
||||
public static byte[] HashData(byte[] source)
|
||||
{
|
||||
using (var md5 = MD5.Create())
|
||||
{
|
||||
return md5.ComputeHash(source);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#nullable enable
|
||||
#if !NET
|
||||
using Renci.SshNet.Abstractions;
|
||||
#endif
|
||||
|
||||
namespace System.Security.Cryptography
|
||||
{
|
||||
internal static class RandomNumberGeneratorExtensions
|
||||
{
|
||||
extension(RandomNumberGenerator)
|
||||
{
|
||||
#if !NET
|
||||
public static byte[] GetBytes(int length)
|
||||
{
|
||||
var random = new byte[length];
|
||||
CryptoAbstraction.Randomizer.GetBytes(random);
|
||||
return random;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace System.Security.Cryptography
|
||||
{
|
||||
internal static class SHA1Extensions
|
||||
{
|
||||
extension(SHA1)
|
||||
{
|
||||
#if !NET
|
||||
public static byte[] HashData(byte[] source)
|
||||
{
|
||||
using (var sha1 = SHA1.Create())
|
||||
{
|
||||
return sha1.ComputeHash(source);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#nullable enable
|
||||
namespace System.Security.Cryptography
|
||||
{
|
||||
internal static class SHA256Extensions
|
||||
{
|
||||
extension(SHA256)
|
||||
{
|
||||
#if !NET
|
||||
public static byte[] HashData(byte[] source)
|
||||
{
|
||||
using (var sha256 = SHA256.Create())
|
||||
{
|
||||
return sha256.ComputeHash(source);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#nullable enable
|
||||
namespace System.Security.Cryptography
|
||||
{
|
||||
internal static class SHA384Extensions
|
||||
{
|
||||
extension(SHA384)
|
||||
{
|
||||
#if !NET
|
||||
public static byte[] HashData(byte[] source)
|
||||
{
|
||||
using (var sha384 = SHA384.Create())
|
||||
{
|
||||
return sha384.ComputeHash(source);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#nullable enable
|
||||
namespace System.Security.Cryptography
|
||||
{
|
||||
internal static class SHA512Extensions
|
||||
{
|
||||
extension(SHA512)
|
||||
{
|
||||
#if !NET
|
||||
public static byte[] HashData(byte[] source)
|
||||
{
|
||||
using (var sha512 = SHA512.Create())
|
||||
{
|
||||
return sha512.ComputeHash(source);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#nullable enable
|
||||
#if NETSTANDARD2_0 || NETFRAMEWORK
|
||||
using System.Collections.Generic;
|
||||
#endif
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal static class StringExtensions
|
||||
{
|
||||
extension(string text)
|
||||
{
|
||||
#if NETSTANDARD2_0 || NETFRAMEWORK
|
||||
public static string Join(char separator, params string?[] value)
|
||||
{
|
||||
return string.Join(separator.ToString(), value);
|
||||
}
|
||||
|
||||
public static string Join(char separator, IEnumerable<string?> value)
|
||||
{
|
||||
return string.Join(separator.ToString(), value);
|
||||
}
|
||||
|
||||
public static string Join(char separator, string?[] value, int startIndex, int count)
|
||||
{
|
||||
return string.Join(separator.ToString(), value, startIndex, count);
|
||||
}
|
||||
|
||||
public int IndexOf(char value, StringComparison comparisonType)
|
||||
{
|
||||
return text.IndexOf(value.ToString(), comparisonType);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Abstractions
|
||||
{
|
||||
internal static class ThreadAbstraction
|
||||
@@ -18,7 +16,7 @@ namespace Renci.SshNet.Abstractions
|
||||
/// </returns>
|
||||
public static Task ExecuteThreadLongRunning(Action action)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(action);
|
||||
ArgumentNullException.ThrowIfNull(action);
|
||||
|
||||
return Task.Factory.StartNew(action,
|
||||
CancellationToken.None,
|
||||
@@ -32,7 +30,7 @@ namespace Renci.SshNet.Abstractions
|
||||
/// <param name="action">The action to execute.</param>
|
||||
public static void ExecuteThread(Action action)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(action);
|
||||
ArgumentNullException.ThrowIfNull(action);
|
||||
|
||||
_ = ThreadPool.QueueUserWorkItem(o => action());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#nullable enable
|
||||
#if !NET
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal static class ThrowExtensions
|
||||
{
|
||||
extension(ObjectDisposedException)
|
||||
{
|
||||
public static void ThrowIf(bool condition, object instance)
|
||||
{
|
||||
if (condition)
|
||||
{
|
||||
Throw(instance);
|
||||
|
||||
static void Throw(object? instance)
|
||||
{
|
||||
throw new ObjectDisposedException(instance?.GetType().FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension(ArgumentNullException)
|
||||
{
|
||||
public static void ThrowIfNull([NotNull] object? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
|
||||
{
|
||||
if (argument is null)
|
||||
{
|
||||
ThrowArgumentNullException(paramName);
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
static void ThrowArgumentNullException(string? paramName)
|
||||
{
|
||||
throw new ArgumentNullException(paramName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension(ArgumentException)
|
||||
{
|
||||
public static void ThrowIfNullOrWhiteSpace([NotNull] string? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(argument))
|
||||
{
|
||||
Throw(argument, paramName);
|
||||
|
||||
[DoesNotReturn]
|
||||
static void Throw(string? argument, string? paramName)
|
||||
{
|
||||
ThrowIfNull(argument, paramName);
|
||||
throw new ArgumentException("The value cannot be an empty string or composed entirely of whitespace.", paramName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ThrowIfNullOrEmpty([NotNull] string? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(argument))
|
||||
{
|
||||
Throw(argument, paramName);
|
||||
|
||||
[DoesNotReturn]
|
||||
static void Throw(string? argument, string? paramName)
|
||||
{
|
||||
ThrowIfNull(argument, paramName);
|
||||
throw new ArgumentException("The value cannot be an empty string.", paramName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension(ArgumentOutOfRangeException)
|
||||
{
|
||||
public static void ThrowIfNegative(long value, [CallerArgumentExpression(nameof(value))] string? paramName = null)
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
Throw(value, paramName);
|
||||
|
||||
[DoesNotReturn]
|
||||
static void Throw(long value, string? paramName)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(paramName, value, "Value must be non-negative.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
/// <summary>
|
||||
@@ -36,7 +34,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentException"><paramref name="username"/> is whitespace or <see langword="null"/>.</exception>
|
||||
protected AuthenticationMethod(string username)
|
||||
{
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(username);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(username);
|
||||
|
||||
Username = username;
|
||||
}
|
||||
|
||||
@@ -186,8 +186,8 @@ namespace Renci.SshNet
|
||||
/// </remarks>
|
||||
private protected BaseClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, IServiceFactory serviceFactory)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(connectionInfo);
|
||||
ThrowHelper.ThrowIfNull(serviceFactory);
|
||||
ArgumentNullException.ThrowIfNull(connectionInfo);
|
||||
ArgumentNullException.ThrowIfNull(serviceFactory);
|
||||
|
||||
_connectionInfo = connectionInfo;
|
||||
_ownsConnectionInfo = ownsConnectionInfo;
|
||||
@@ -467,7 +467,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ObjectDisposedException">The current instance is disposed.</exception>
|
||||
protected void CheckDisposed()
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_isDisposed, this);
|
||||
ObjectDisposedException.ThrowIf(_isDisposed, this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -52,8 +52,8 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SshAuthenticationException">Failed to authenticate the client.</exception>
|
||||
public void Authenticate(IConnectionInfoInternal connectionInfo, ISession session)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(connectionInfo);
|
||||
ThrowHelper.ThrowIfNull(session);
|
||||
ArgumentNullException.ThrowIfNull(connectionInfo);
|
||||
ArgumentNullException.ThrowIfNull(session);
|
||||
|
||||
session.RegisterMessage("SSH_MSG_USERAUTH_FAILURE");
|
||||
session.RegisterMessage("SSH_MSG_USERAUTH_SUCCESS");
|
||||
@@ -105,12 +105,7 @@ namespace Renci.SshNet
|
||||
{
|
||||
authenticationException = new SshAuthenticationException(string.Format(CultureInfo.InvariantCulture,
|
||||
"No suitable authentication method found to complete authentication ({0}).",
|
||||
#if NET
|
||||
string.Join(',', allowedAuthenticationMethods)))
|
||||
#else
|
||||
string.Join(",", allowedAuthenticationMethods)))
|
||||
#endif
|
||||
;
|
||||
string.Join(',', allowedAuthenticationMethods)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Renci.SshNet.Common
|
||||
public ChannelDataEventArgs(uint channelNumber, ArraySegment<byte> data)
|
||||
: base(channelNumber)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(data.Array);
|
||||
ArgumentNullException.ThrowIfNull(data.Array);
|
||||
|
||||
Data = data;
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace Renci.SshNet.Common
|
||||
#endif
|
||||
ValidateBufferArguments(buffer, offset, count);
|
||||
|
||||
ThrowHelper.ThrowObjectDisposedIf(_isDisposed, this);
|
||||
ObjectDisposedException.ThrowIf(_isDisposed, this);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Renci.SshNet.Common
|
||||
/// <exception cref="ArgumentNullException"><paramref name="info"/> is <see langword="null"/>.</exception>
|
||||
public ChannelRequestEventArgs(RequestInfo info)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(info);
|
||||
ArgumentNullException.ThrowIfNull(info);
|
||||
|
||||
Info = info;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
#if !NET
|
||||
using System.Collections.Generic;
|
||||
#endif
|
||||
using System.Globalization;
|
||||
#if !NET
|
||||
using System.IO;
|
||||
@@ -193,7 +195,7 @@ namespace Renci.SshNet.Common
|
||||
/// </remarks>
|
||||
public static byte[] Take(this byte[] value, int offset, int count)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(value);
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
@@ -225,7 +227,7 @@ namespace Renci.SshNet.Common
|
||||
/// </remarks>
|
||||
public static byte[] Take(this byte[] value, int count)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(value);
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
@@ -244,8 +246,8 @@ namespace Renci.SshNet.Common
|
||||
|
||||
public static bool IsEqualTo(this byte[] left, byte[] right)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(left);
|
||||
ThrowHelper.ThrowIfNull(right);
|
||||
ArgumentNullException.ThrowIfNull(left);
|
||||
ArgumentNullException.ThrowIfNull(right);
|
||||
|
||||
return left.AsSpan().SequenceEqual(right);
|
||||
}
|
||||
@@ -259,7 +261,7 @@ namespace Renci.SshNet.Common
|
||||
/// </returns>
|
||||
public static byte[] TrimLeadingZeros(this byte[] value)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(value);
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
for (var i = 0; i < value.Length; i++)
|
||||
{
|
||||
@@ -329,13 +331,6 @@ namespace Renci.SshNet.Common
|
||||
return socket.Connected;
|
||||
}
|
||||
|
||||
internal static string Join(this IEnumerable<string> values, string separator)
|
||||
{
|
||||
// Used to avoid analyzers asking to "use an overload with a char parameter"
|
||||
// which is not available on all targets.
|
||||
return string.Join(separator, values);
|
||||
}
|
||||
|
||||
#if !NET
|
||||
internal static bool TryAdd<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue value)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Renci.SshNet.Security;
|
||||
|
||||
namespace Renci.SshNet.Common
|
||||
@@ -97,16 +97,16 @@ namespace Renci.SshNet.Common
|
||||
/// <exception cref="ArgumentNullException"><paramref name="host"/> is <see langword="null"/>.</exception>
|
||||
public HostKeyEventArgs(KeyHostAlgorithm host)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(host);
|
||||
ArgumentNullException.ThrowIfNull(host);
|
||||
|
||||
CanTrust = true;
|
||||
HostKey = host.KeyData.GetBytes();
|
||||
HostKeyName = host.Name;
|
||||
KeyLength = host.Key.KeyLength;
|
||||
|
||||
_lazyFingerPrint = new Lazy<byte[]>(() => CryptoAbstraction.HashMD5(HostKey));
|
||||
_lazyFingerPrint = new Lazy<byte[]>(() => MD5.HashData(HostKey));
|
||||
|
||||
_lazyFingerPrintSHA256 = new Lazy<string>(() => Convert.ToBase64String(CryptoAbstraction.HashSHA256(HostKey)).TrimEnd('='));
|
||||
_lazyFingerPrintSHA256 = new Lazy<string>(() => Convert.ToBase64String(SHA256.HashData(HostKey)).TrimEnd('='));
|
||||
|
||||
_lazyFingerPrintMD5 = new Lazy<string>(() =>
|
||||
{
|
||||
|
||||
@@ -7,7 +7,9 @@ namespace Renci.SshNet.Common
|
||||
{
|
||||
public bool TryEnter()
|
||||
{
|
||||
#pragma warning disable CA2002 // Do not lock on objects with weak identity
|
||||
return Monitor.TryEnter(this);
|
||||
#pragma warning restore CA2002 // Do not lock on objects with weak identity
|
||||
}
|
||||
|
||||
public void Exit()
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace Renci.SshNet.Common
|
||||
|
||||
public static string Create(byte[] data, int indentLevel)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(data);
|
||||
ThrowHelper.ThrowIfNegative(indentLevel);
|
||||
ArgumentNullException.ThrowIfNull(data);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(indentLevel);
|
||||
|
||||
const int lineWidth = 16;
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace Renci.SshNet.Common
|
||||
{
|
||||
Debug.Assert(Monitor.IsEntered(_sync));
|
||||
|
||||
ThrowHelper.ThrowObjectDisposedIf(_disposed, this);
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
_buffer.EnsureAvailableSpace(buffer.Length);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Renci.SshNet.Common
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is not within <see cref="IPEndPoint.MinPort" /> and <see cref="IPEndPoint.MaxPort" />.</exception>
|
||||
internal PortForwardEventArgs(string host, uint port)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(host);
|
||||
ArgumentNullException.ThrowIfNull(host);
|
||||
port.ValidatePort();
|
||||
|
||||
OriginatorHost = host;
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Renci.SshNet.Common
|
||||
/// <exception cref="ArgumentException"><paramref name="path"/> is empty ("").</exception>
|
||||
public static PosixPath CreateAbsoluteOrRelativeFilePath(string path)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
var posixPath = new PosixPath();
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Renci.SshNet.Common
|
||||
/// </remarks>
|
||||
public static string GetFileName(string path)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
var pathEnd = path.LastIndexOf('/');
|
||||
if (pathEnd == -1)
|
||||
@@ -119,7 +119,7 @@ namespace Renci.SshNet.Common
|
||||
/// <exception cref="ArgumentNullException"><paramref name="path"/> is <see langword="null"/>.</exception>
|
||||
public static string GetDirectoryName(string path)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
var pathEnd = path.LastIndexOf('/');
|
||||
if (pathEnd == -1)
|
||||
|
||||
@@ -11,7 +11,9 @@ namespace Renci.SshNet.Common
|
||||
#if NETFRAMEWORK
|
||||
[Serializable]
|
||||
#endif
|
||||
#pragma warning disable CA1032 // Implement standard exception constructors
|
||||
public class SftpException : SshException
|
||||
#pragma warning restore CA1032 // Implement standard exception constructors
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the status code that is associated with this exception.
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace Renci.SshNet.Common
|
||||
/// <exception cref="ArgumentNullException"><paramref name="data"/> is <see langword="null"/>.</exception>
|
||||
public void Load(byte[] data)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(data);
|
||||
ArgumentNullException.ThrowIfNull(data);
|
||||
|
||||
LoadInternal(data, 0, data.Length);
|
||||
}
|
||||
@@ -105,7 +105,7 @@ namespace Renci.SshNet.Common
|
||||
/// <exception cref="ArgumentNullException"><paramref name="data"/> is <see langword="null"/>.</exception>
|
||||
public void Load(byte[] data, int offset, int count)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(data);
|
||||
ArgumentNullException.ThrowIfNull(data);
|
||||
|
||||
LoadInternal(data, offset, count);
|
||||
}
|
||||
@@ -386,11 +386,7 @@ namespace Renci.SshNet.Common
|
||||
/// <param name="data">name-list data to write.</param>
|
||||
protected void Write(string[] data)
|
||||
{
|
||||
#if NET
|
||||
Write(string.Join(',', data), Ascii);
|
||||
#else
|
||||
Write(string.Join(",", data), Ascii);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace Renci.SshNet.Common
|
||||
/// <exception cref="ArgumentNullException"><paramref name="data"/> is <see langword="null"/>.</exception>
|
||||
public void Write(byte[] data)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(data);
|
||||
ArgumentNullException.ThrowIfNull(data);
|
||||
|
||||
Write(data, 0, data.Length);
|
||||
}
|
||||
@@ -126,8 +126,8 @@ namespace Renci.SshNet.Common
|
||||
/// <exception cref="ArgumentNullException"><paramref name="encoding"/> is <see langword="null"/>.</exception>
|
||||
public void Write(string s, Encoding encoding)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(s);
|
||||
ThrowHelper.ThrowIfNull(encoding);
|
||||
ArgumentNullException.ThrowIfNull(s);
|
||||
ArgumentNullException.ThrowIfNull(encoding);
|
||||
|
||||
#if NET
|
||||
ReadOnlySpan<char> value = s;
|
||||
@@ -192,7 +192,7 @@ namespace Renci.SshNet.Common
|
||||
/// <exception cref="ArgumentNullException"><paramref name="buffer"/> is <see langword="null"/>.</exception>
|
||||
public void WriteBinary(byte[] buffer)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(buffer);
|
||||
ArgumentNullException.ThrowIfNull(buffer);
|
||||
|
||||
WriteBinary(buffer, 0, buffer.Length);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma warning disable
|
||||
#if !NET
|
||||
// Copied verbatim from https://github.com/dotnet/runtime/blob/261611930d6b436d7c4395450356b624d903d9bf/src/libraries/Common/src/System/Threading/Tasks/TaskToAsyncResult.cs
|
||||
// Copied verbatim from https://github.com/dotnet/runtime/blob/7b2de1e5ed6368c536ee646346e6fd81939e6fe6/src/libraries/Common/src/System/Threading/Tasks/TaskToAsyncResult.cs
|
||||
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
@@ -35,15 +35,7 @@ namespace System.Threading.Tasks
|
||||
/// </remarks>
|
||||
public static IAsyncResult Begin(Task task, AsyncCallback? callback, object? state)
|
||||
{
|
||||
#if NET
|
||||
ArgumentNullException.ThrowIfNull(task);
|
||||
#else
|
||||
if (task is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(task));
|
||||
}
|
||||
#endif
|
||||
|
||||
return new TaskAsyncResult(task, state, callback);
|
||||
}
|
||||
|
||||
@@ -72,14 +64,7 @@ namespace System.Threading.Tasks
|
||||
/// <exception cref="ArgumentException"><paramref name="asyncResult"/> was not produced by a call to <see cref="Begin"/>.</exception>
|
||||
public static Task Unwrap(IAsyncResult asyncResult)
|
||||
{
|
||||
#if NET
|
||||
ArgumentNullException.ThrowIfNull(asyncResult);
|
||||
#else
|
||||
if (asyncResult is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(asyncResult));
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((asyncResult as TaskAsyncResult)?._task is not Task task)
|
||||
{
|
||||
@@ -101,14 +86,7 @@ namespace System.Threading.Tasks
|
||||
/// </exception>
|
||||
public static Task<TResult> Unwrap<TResult>(IAsyncResult asyncResult)
|
||||
{
|
||||
#if NET
|
||||
ArgumentNullException.ThrowIfNull(asyncResult);
|
||||
#else
|
||||
if (asyncResult is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(asyncResult));
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((asyncResult as TaskAsyncResult)?._task is not Task<TResult> task)
|
||||
{
|
||||
|
||||
@@ -1,93 +1,19 @@
|
||||
#nullable enable
|
||||
#if !NET
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Renci.SshNet.Common
|
||||
{
|
||||
internal static class ThrowHelper
|
||||
{
|
||||
public static void ThrowObjectDisposedIf(bool condition, object instance)
|
||||
{
|
||||
#if NET
|
||||
ObjectDisposedException.ThrowIf(condition, instance);
|
||||
#else
|
||||
if (condition)
|
||||
{
|
||||
Throw(instance);
|
||||
|
||||
static void Throw(object? instance)
|
||||
{
|
||||
throw new ObjectDisposedException(instance?.GetType().FullName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void ThrowIfNull([NotNull] object? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
|
||||
{
|
||||
#if NET
|
||||
ArgumentNullException.ThrowIfNull(argument, paramName);
|
||||
#else
|
||||
if (argument is null)
|
||||
{
|
||||
Throw(paramName);
|
||||
|
||||
[DoesNotReturn]
|
||||
static void Throw(string? paramName)
|
||||
{
|
||||
throw new ArgumentNullException(paramName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void ThrowIfNullOrWhiteSpace([NotNull] string? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
|
||||
{
|
||||
#if NET
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(argument, paramName);
|
||||
#else
|
||||
if (string.IsNullOrWhiteSpace(argument))
|
||||
{
|
||||
Throw(argument, paramName);
|
||||
|
||||
[DoesNotReturn]
|
||||
static void Throw(string? argument, string? paramName)
|
||||
{
|
||||
ThrowIfNull(argument, paramName);
|
||||
throw new ArgumentException("The value cannot be an empty string or composed entirely of whitespace.", paramName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static void ThrowIfNullOrEmpty([NotNull] string? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
|
||||
{
|
||||
#if NET
|
||||
ArgumentException.ThrowIfNullOrEmpty(argument, paramName);
|
||||
#else
|
||||
if (string.IsNullOrEmpty(argument))
|
||||
{
|
||||
Throw(argument, paramName);
|
||||
|
||||
[DoesNotReturn]
|
||||
static void Throw(string? argument, string? paramName)
|
||||
{
|
||||
ThrowIfNull(argument, paramName);
|
||||
throw new ArgumentException("The value cannot be an empty string.", paramName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !NET
|
||||
// A rough copy of
|
||||
// https://github.com/dotnet/runtime/blob/1d1bf92fcf43aa6981804dc53c5174445069c9e4/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs#L960C13-L974C10
|
||||
// for lower targets.
|
||||
public static void ValidateBufferArguments(byte[] buffer, int offset, int count)
|
||||
{
|
||||
ThrowIfNull(buffer);
|
||||
ThrowIfNegative(offset);
|
||||
ArgumentNullException.ThrowIfNull(buffer);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(offset);
|
||||
|
||||
if ((uint)count > buffer.Length - offset)
|
||||
{
|
||||
@@ -102,24 +28,6 @@ namespace Renci.SshNet.Common
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public static void ThrowIfNegative(long value, [CallerArgumentExpression(nameof(value))] string? paramName = null)
|
||||
{
|
||||
#if NET
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(value, paramName);
|
||||
#else
|
||||
if (value < 0)
|
||||
{
|
||||
Throw(value, paramName);
|
||||
|
||||
[DoesNotReturn]
|
||||
static void Throw(long value, string? paramName)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(paramName, value, "Value must be non-negative.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Renci.SshNet.Connection
|
||||
|
||||
protected ConnectorBase(ISocketFactory socketFactory, ILoggerFactory loggerFactory)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(socketFactory);
|
||||
ArgumentNullException.ThrowIfNull(socketFactory);
|
||||
|
||||
SocketFactory = socketFactory;
|
||||
_logger = loggerFactory.CreateLogger(GetType());
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Connection
|
||||
{
|
||||
/// <summary>
|
||||
@@ -33,8 +31,8 @@ namespace Renci.SshNet.Connection
|
||||
/// <exception cref="ArgumentNullException"><paramref name="softwareVersion"/> is <see langword="null"/>.</exception>
|
||||
public SshIdentification(string protocolVersion, string softwareVersion, string comments)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(protocolVersion);
|
||||
ThrowHelper.ThrowIfNull(softwareVersion);
|
||||
ArgumentNullException.ThrowIfNull(protocolVersion);
|
||||
ArgumentNullException.ThrowIfNull(softwareVersion);
|
||||
|
||||
ProtocolVersion = protocolVersion;
|
||||
SoftwareVersion = softwareVersion;
|
||||
|
||||
@@ -325,17 +325,17 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentException">No <paramref name="authenticationMethods"/> specified.</exception>
|
||||
public ConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params AuthenticationMethod[] authenticationMethods)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(host);
|
||||
ArgumentNullException.ThrowIfNull(host);
|
||||
port.ValidatePort();
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(username);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(username);
|
||||
|
||||
if (proxyType != ProxyTypes.None)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(proxyHost);
|
||||
ArgumentNullException.ThrowIfNull(proxyHost);
|
||||
proxyPort.ValidatePort();
|
||||
}
|
||||
|
||||
ThrowHelper.ThrowIfNull(authenticationMethods);
|
||||
ArgumentNullException.ThrowIfNull(authenticationMethods);
|
||||
|
||||
if (authenticationMethods.Length == 0)
|
||||
{
|
||||
@@ -459,7 +459,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SshAuthenticationException">No suitable authentication method found to complete authentication, or permission denied.</exception>
|
||||
internal void Authenticate(ISession session, IServiceFactory serviceFactory)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(serviceFactory);
|
||||
ArgumentNullException.ThrowIfNull(serviceFactory);
|
||||
|
||||
IsAuthenticated = false;
|
||||
var clientAuthentication = serviceFactory.CreateClientAuthentication();
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
/// <summary>
|
||||
@@ -28,8 +26,8 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="expect"/> or <paramref name="action"/> is <see langword="null"/>.</exception>
|
||||
public ExpectAction(Regex expect, Action<string> action)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(expect);
|
||||
ThrowHelper.ThrowIfNull(action);
|
||||
ArgumentNullException.ThrowIfNull(expect);
|
||||
ArgumentNullException.ThrowIfNull(action);
|
||||
|
||||
Expect = expect;
|
||||
Action = action;
|
||||
@@ -43,8 +41,8 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="expect"/> or <paramref name="action"/> is <see langword="null"/>.</exception>
|
||||
public ExpectAction(string expect, Action<string> action)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(expect);
|
||||
ThrowHelper.ThrowIfNull(action);
|
||||
ArgumentNullException.ThrowIfNull(expect);
|
||||
ArgumentNullException.ThrowIfNull(action);
|
||||
|
||||
Expect = new Regex(Regex.Escape(expect));
|
||||
Action = action;
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ObjectDisposedException">The current instance is disposed.</exception>
|
||||
protected override void CheckDisposed()
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_isDisposed, this);
|
||||
ObjectDisposedException.ThrowIf(_isDisposed, this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -182,9 +182,7 @@ namespace Renci.SshNet
|
||||
{
|
||||
if (e is null)
|
||||
{
|
||||
#pragma warning disable CA2000 // Dispose objects before losing scope
|
||||
e = new SocketAsyncEventArgs();
|
||||
#pragma warning restore CA2000 // Dispose objects before losing scope
|
||||
e.Completed += AcceptCompleted;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -91,8 +91,8 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is greater than <see cref="IPEndPoint.MaxPort" />.</exception>
|
||||
public ForwardedPortLocal(string boundHost, uint boundPort, string host, uint port)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(boundHost);
|
||||
ThrowHelper.ThrowIfNull(host);
|
||||
ArgumentNullException.ThrowIfNull(boundHost);
|
||||
ArgumentNullException.ThrowIfNull(host);
|
||||
|
||||
boundPort.ValidatePort();
|
||||
port.ValidatePort();
|
||||
@@ -158,7 +158,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ObjectDisposedException">The current instance is disposed.</exception>
|
||||
protected override void CheckDisposed()
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_isDisposed, this);
|
||||
ObjectDisposedException.ThrowIf(_isDisposed, this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -212,9 +212,7 @@ namespace Renci.SshNet
|
||||
{
|
||||
if (e is null)
|
||||
{
|
||||
#pragma warning disable CA2000 // Dispose objects before losing scope
|
||||
e = new SocketAsyncEventArgs();
|
||||
#pragma warning restore CA2000 // Dispose objects before losing scope
|
||||
e.Completed += AcceptCompleted;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -88,8 +88,8 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port" /> is greater than <see cref="IPEndPoint.MaxPort" />.</exception>
|
||||
public ForwardedPortRemote(IPAddress boundHostAddress, uint boundPort, IPAddress hostAddress, uint port)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(boundHostAddress);
|
||||
ThrowHelper.ThrowIfNull(hostAddress);
|
||||
ArgumentNullException.ThrowIfNull(boundHostAddress);
|
||||
ArgumentNullException.ThrowIfNull(hostAddress);
|
||||
|
||||
boundPort.ValidatePort();
|
||||
port.ValidatePort();
|
||||
@@ -227,7 +227,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ObjectDisposedException">The current instance is disposed.</exception>
|
||||
protected override void CheckDisposed()
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_isDisposed, this);
|
||||
ObjectDisposedException.ThrowIf(_isDisposed, this);
|
||||
}
|
||||
|
||||
private void Session_ChannelOpening(object sender, MessageEventArgs<ChannelOpenMessage> e)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
/// <summary>
|
||||
@@ -22,7 +20,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="message"/> is <see langword="null"/>.</exception>
|
||||
public MessageEventArgs(T message)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(message);
|
||||
ArgumentNullException.ThrowIfNull(message);
|
||||
|
||||
Message = message;
|
||||
}
|
||||
|
||||
@@ -55,11 +55,7 @@ namespace Renci.SshNet.Messages.Authentication
|
||||
PartialSuccess = ReadBoolean();
|
||||
if (PartialSuccess)
|
||||
{
|
||||
#if NET
|
||||
Message = string.Join(',', AllowedAuthentications);
|
||||
#else
|
||||
Message = string.Join(",", AllowedAuthentications);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Renci.SshNet.Common;
|
||||
using System;
|
||||
|
||||
namespace Renci.SshNet.Messages.Connection
|
||||
{
|
||||
@@ -89,7 +89,7 @@ namespace Renci.SshNet.Messages.Connection
|
||||
public ChannelDataMessage(uint localChannelNumber, byte[] data)
|
||||
: base(localChannelNumber)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(data);
|
||||
ArgumentNullException.ThrowIfNull(data);
|
||||
|
||||
Data = data;
|
||||
Offset = 0;
|
||||
@@ -106,7 +106,7 @@ namespace Renci.SshNet.Messages.Connection
|
||||
public ChannelDataMessage(uint localChannelNumber, byte[] data, int offset, int size)
|
||||
: base(localChannelNumber)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(data);
|
||||
ArgumentNullException.ThrowIfNull(data);
|
||||
|
||||
Data = data;
|
||||
Offset = offset;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Messages.Connection
|
||||
{
|
||||
/// <summary>
|
||||
@@ -106,7 +104,7 @@ namespace Renci.SshNet.Messages.Connection
|
||||
/// <exception cref="ArgumentNullException"><paramref name="info"/> is <see langword="null"/>.</exception>
|
||||
public ChannelOpenMessage(uint channelNumber, uint initialWindowSize, uint maximumPacketSize, ChannelOpenInfo info)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(info);
|
||||
ArgumentNullException.ThrowIfNull(info);
|
||||
|
||||
ChannelType = Ascii.GetBytes(info.ChannelType);
|
||||
LocalChannelNumber = channelNumber;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Messages.Connection
|
||||
{
|
||||
/// <summary>
|
||||
@@ -81,8 +79,8 @@ namespace Renci.SshNet.Messages.Connection
|
||||
public ExecRequestInfo(string command, Encoding encoding)
|
||||
: this()
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(command);
|
||||
ThrowHelper.ThrowIfNull(encoding);
|
||||
ArgumentNullException.ThrowIfNull(command);
|
||||
ArgumentNullException.ThrowIfNull(encoding);
|
||||
|
||||
_command = encoding.GetBytes(command);
|
||||
Encoding = encoding;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Compression;
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace Renci.SshNet.Messages
|
||||
var paddingLength = GetPaddingLength(paddingMultiplier, excludePacketLengthFieldWhenPadding ? packetLength - 4 : packetLength);
|
||||
|
||||
// add padding bytes
|
||||
var paddingBytes = CryptoAbstraction.GenerateRandom(paddingLength);
|
||||
var paddingBytes = RandomNumberGenerator.GetBytes(paddingLength);
|
||||
sshDataStream.Write(paddingBytes, 0, paddingLength);
|
||||
|
||||
var packetDataLength = GetPacketDataLength(messageLength, paddingLength);
|
||||
@@ -127,7 +127,7 @@ namespace Renci.SshNet.Messages
|
||||
WriteBytes(sshDataStream);
|
||||
|
||||
// add padding bytes
|
||||
var paddingBytes = CryptoAbstraction.GenerateRandom(paddingLength);
|
||||
var paddingBytes = RandomNumberGenerator.GetBytes(paddingLength);
|
||||
sshDataStream.Write(paddingBytes, 0, paddingLength);
|
||||
|
||||
return sshDataStream.ToArray();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Messages.Transport
|
||||
{
|
||||
/// <summary>
|
||||
@@ -47,7 +45,7 @@ namespace Renci.SshNet.Messages.Transport
|
||||
/// <param name="data">The data.</param>
|
||||
public IgnoreMessage(byte[] data)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(data);
|
||||
ArgumentNullException.ThrowIfNull(data);
|
||||
|
||||
Data = data;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Renci.SshNet.Abstractions;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Renci.SshNet.Messages.Transport
|
||||
{
|
||||
@@ -12,7 +12,7 @@ namespace Renci.SshNet.Messages.Transport
|
||||
/// </summary>
|
||||
public KeyExchangeInitMessage()
|
||||
{
|
||||
Cookie = CryptoAbstraction.GenerateRandom(16);
|
||||
Cookie = RandomNumberGenerator.GetBytes(16);
|
||||
}
|
||||
|
||||
#region Message Properties
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
@@ -73,7 +72,6 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="password"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid, or <paramref name="username"/> is <see langword="null"/> or contains only whitespace characters.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
|
||||
public NetConfClient(string host, int port, string username, string password)
|
||||
: this(new PasswordConnectionInfo(host, port, username, password), ownsConnectionInfo: true)
|
||||
{
|
||||
@@ -102,7 +100,6 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="keyFiles"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid, -or- <paramref name="username"/> is <see langword="null"/> or contains only whitespace characters.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
|
||||
public NetConfClient(string host, int port, string username, params IPrivateKeySource[] keyFiles)
|
||||
: this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), ownsConnectionInfo: true)
|
||||
{
|
||||
@@ -299,11 +296,8 @@ namespace Renci.SshNet
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (_netConfSession != null)
|
||||
{
|
||||
_netConfSession.Dispose();
|
||||
_netConfSession = null;
|
||||
}
|
||||
_netConfSession?.Dispose();
|
||||
_netConfSession = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -213,17 +213,11 @@ namespace Renci.SshNet.NetConf
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (_serverCapabilitiesConfirmed != null)
|
||||
{
|
||||
_serverCapabilitiesConfirmed.Dispose();
|
||||
_serverCapabilitiesConfirmed = null;
|
||||
}
|
||||
_serverCapabilitiesConfirmed?.Dispose();
|
||||
_serverCapabilitiesConfirmed = null;
|
||||
|
||||
if (_rpcReplyReceived != null)
|
||||
{
|
||||
_rpcReplyReceived.Dispose();
|
||||
_rpcReplyReceived = null;
|
||||
}
|
||||
_rpcReplyReceived?.Dispose();
|
||||
_rpcReplyReceived = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages;
|
||||
using Renci.SshNet.Messages.Authentication;
|
||||
|
||||
@@ -44,7 +43,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="session" /> is <see langword="null"/>.</exception>
|
||||
public override AuthenticationResult Authenticate(Session session)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(session);
|
||||
ArgumentNullException.ThrowIfNull(session);
|
||||
|
||||
session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
|
||||
session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived;
|
||||
|
||||
@@ -9,7 +9,9 @@ using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
#if !NET
|
||||
using Renci.SshNet.Common;
|
||||
#endif
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
@@ -486,8 +488,8 @@ namespace Renci.SshNet
|
||||
|
||||
public virtual void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(array);
|
||||
ThrowHelper.ThrowIfNegative(arrayIndex);
|
||||
ArgumentNullException.ThrowIfNull(array);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(arrayIndex);
|
||||
|
||||
if (array.Length - arrayIndex < Count)
|
||||
{
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace Renci.SshNet
|
||||
public PasswordAuthenticationMethod(string username, byte[] password)
|
||||
: base(username)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(password);
|
||||
ArgumentNullException.ThrowIfNull(password);
|
||||
|
||||
_password = password;
|
||||
_requestMessage = new RequestMessagePassword(ServiceName.Connection, Username, _password);
|
||||
@@ -85,7 +85,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="session" /> is <see langword="null"/>.</exception>
|
||||
public override AuthenticationResult Authenticate(Session session)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(session);
|
||||
ArgumentNullException.ThrowIfNull(session);
|
||||
|
||||
_session = session;
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace Renci.SshNet
|
||||
public PrivateKeyAuthenticationMethod(string username, params IPrivateKeySource[] keyFiles)
|
||||
: base(username)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(keyFiles);
|
||||
ArgumentNullException.ThrowIfNull(keyFiles);
|
||||
|
||||
KeyFiles = new Collection<IPrivateKeySource>(keyFiles);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Renci.SshNet
|
||||
/// </summary>
|
||||
public Key Parse()
|
||||
{
|
||||
var keyReader = new SshDataStream(_data);
|
||||
using var keyReader = new SshDataStream(_data);
|
||||
|
||||
// check magic header
|
||||
var authMagic = "openssh-key-v1\0"u8;
|
||||
@@ -171,7 +171,7 @@ namespace Renci.SshNet
|
||||
// now parse the data we called the private key, it actually contains the public key again
|
||||
// so we need to parse through it to get the private key bytes, plus there's some
|
||||
// validation we need to do.
|
||||
var privateKeyReader = new SshDataStream(privateKeyBytes);
|
||||
using var privateKeyReader = new SshDataStream(privateKeyBytes);
|
||||
|
||||
// check ints should match, they wouldn't match for example if the wrong passphrase was supplied
|
||||
var checkInt1 = (int)privateKeyReader.ReadUInt32();
|
||||
|
||||
@@ -42,11 +42,8 @@ namespace Renci.SshNet
|
||||
{
|
||||
throw new SshPassPhraseNullOrEmptyException("Private key is encrypted but passphrase is empty.");
|
||||
}
|
||||
#if NET
|
||||
|
||||
var binarySalt = Convert.FromHexString(_salt);
|
||||
#else
|
||||
var binarySalt = Org.BouncyCastle.Utilities.Encoders.Hex.Decode(_salt);
|
||||
#endif
|
||||
CipherInfo cipher;
|
||||
switch (_cipherName)
|
||||
{
|
||||
|
||||
@@ -9,7 +9,6 @@ using System.Text;
|
||||
using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Security;
|
||||
using Renci.SshNet.Security.Cryptography.Ciphers;
|
||||
@@ -72,22 +71,18 @@ namespace Renci.SshNet
|
||||
switch (_version)
|
||||
{
|
||||
case "3":
|
||||
ThrowHelper.ThrowIfNullOrEmpty(_argon2Type);
|
||||
ThrowHelper.ThrowIfNullOrEmpty(_argon2Iterations);
|
||||
ThrowHelper.ThrowIfNullOrEmpty(_argon2Memory);
|
||||
ThrowHelper.ThrowIfNullOrEmpty(_argon2Parallelism);
|
||||
ThrowHelper.ThrowIfNullOrEmpty(_argon2Salt);
|
||||
ArgumentException.ThrowIfNullOrEmpty(_argon2Type);
|
||||
ArgumentException.ThrowIfNullOrEmpty(_argon2Iterations);
|
||||
ArgumentException.ThrowIfNullOrEmpty(_argon2Memory);
|
||||
ArgumentException.ThrowIfNullOrEmpty(_argon2Parallelism);
|
||||
ArgumentException.ThrowIfNullOrEmpty(_argon2Salt);
|
||||
|
||||
var keyData = Argon2(
|
||||
_argon2Type,
|
||||
Convert.ToInt32(_argon2Iterations),
|
||||
Convert.ToInt32(_argon2Memory),
|
||||
Convert.ToInt32(_argon2Parallelism),
|
||||
#if NET
|
||||
Convert.FromHexString(_argon2Salt),
|
||||
#else
|
||||
Org.BouncyCastle.Utilities.Encoders.Hex.Decode(_argon2Salt),
|
||||
#endif
|
||||
_passPhrase);
|
||||
|
||||
cipherKey = keyData.Take(32);
|
||||
@@ -103,7 +98,7 @@ namespace Renci.SshNet
|
||||
cipherKey = keyData.Take(32);
|
||||
cipherIV = new byte[16];
|
||||
|
||||
macKey = CryptoAbstraction.HashSHA1(Encoding.UTF8.GetBytes("putty-private-key-file-mac-key" + _passPhrase)).Take(20);
|
||||
macKey = SHA1.HashData(Encoding.UTF8.GetBytes("putty-private-key-file-mac-key" + _passPhrase)).Take(20);
|
||||
hmac = new HMACSHA1(macKey);
|
||||
|
||||
break;
|
||||
@@ -124,7 +119,7 @@ namespace Renci.SshNet
|
||||
hmac = new HMACSHA256(Array.Empty<byte>());
|
||||
break;
|
||||
case "2":
|
||||
var macKey = CryptoAbstraction.HashSHA1(Encoding.UTF8.GetBytes("putty-private-key-file-mac-key"));
|
||||
var macKey = SHA1.HashData(Encoding.UTF8.GetBytes("putty-private-key-file-mac-key"));
|
||||
hmac = new HMACSHA1(macKey);
|
||||
break;
|
||||
default:
|
||||
@@ -153,21 +148,19 @@ namespace Renci.SshNet
|
||||
{
|
||||
macValue = hmac.ComputeHash(macData);
|
||||
}
|
||||
#if NET
|
||||
|
||||
var reference = Convert.FromHexString(_mac);
|
||||
#else
|
||||
var reference = Org.BouncyCastle.Utilities.Encoders.Hex.Decode(_mac);
|
||||
#endif
|
||||
|
||||
if (!macValue.SequenceEqual(reference))
|
||||
{
|
||||
throw new SshException("MAC verification failed for PuTTY key file");
|
||||
}
|
||||
|
||||
var publicKeyReader = new SshDataStream(_publicKey);
|
||||
using var publicKeyReader = new SshDataStream(_publicKey);
|
||||
var keyType = publicKeyReader.ReadString(Encoding.UTF8);
|
||||
Debug.Assert(keyType == _algorithmName, $"{nameof(keyType)} is not the same as {nameof(_algorithmName)}");
|
||||
|
||||
var privateKeyReader = new SshDataStream(privateKey);
|
||||
using var privateKeyReader = new SshDataStream(privateKey);
|
||||
|
||||
Key parsedKey;
|
||||
|
||||
|
||||
@@ -28,22 +28,22 @@ namespace Renci.SshNet
|
||||
|
||||
public Key Parse()
|
||||
{
|
||||
var reader = new SshDataStream(_data);
|
||||
var magicNumber = reader.ReadUInt32();
|
||||
using var dataReader = new SshDataStream(_data);
|
||||
var magicNumber = dataReader.ReadUInt32();
|
||||
if (magicNumber != 0x3f6ff9eb)
|
||||
{
|
||||
throw new SshException("Invalid SSH2 private key.");
|
||||
}
|
||||
|
||||
_ = reader.ReadUInt32(); // Read total bytes length including magic number
|
||||
var keyType = reader.ReadString(SshData.Ascii);
|
||||
var ssh2CipherName = reader.ReadString(SshData.Ascii);
|
||||
var blobSize = (int)reader.ReadUInt32();
|
||||
_ = dataReader.ReadUInt32(); // Read total bytes length including magic number
|
||||
var keyType = dataReader.ReadString(SshData.Ascii);
|
||||
var ssh2CipherName = dataReader.ReadString(SshData.Ascii);
|
||||
var blobSize = (int)dataReader.ReadUInt32();
|
||||
|
||||
byte[] keyData;
|
||||
if (ssh2CipherName == "none")
|
||||
{
|
||||
keyData = reader.ReadBytes(blobSize);
|
||||
keyData = dataReader.ReadBytes(blobSize);
|
||||
}
|
||||
else if (ssh2CipherName == "3des-cbc")
|
||||
{
|
||||
@@ -53,17 +53,17 @@ namespace Renci.SshNet
|
||||
}
|
||||
|
||||
var key = GetCipherKey(_passPhrase, 192 / 8);
|
||||
var ssh2Сipher = new TripleDesCipher(key, new byte[8], CipherMode.CBC, pkcs7Padding: false);
|
||||
keyData = ssh2Сipher.Decrypt(reader.ReadBytes(blobSize));
|
||||
using var ssh2Сipher = new TripleDesCipher(key, new byte[8], CipherMode.CBC, pkcs7Padding: false);
|
||||
keyData = ssh2Сipher.Decrypt(dataReader.ReadBytes(blobSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SshException(string.Format("Cipher method '{0}' is not supported.", ssh2CipherName));
|
||||
}
|
||||
|
||||
reader = new SshDataStream(keyData);
|
||||
using var keyReader = new SshDataStream(keyData);
|
||||
|
||||
var decryptedLength = reader.ReadUInt32();
|
||||
var decryptedLength = keyReader.ReadUInt32();
|
||||
|
||||
if (decryptedLength > blobSize - 4)
|
||||
{
|
||||
@@ -72,12 +72,12 @@ namespace Renci.SshNet
|
||||
|
||||
if (keyType.Contains("rsa"))
|
||||
{
|
||||
var exponent = ReadBigIntWithBits(reader);
|
||||
var d = ReadBigIntWithBits(reader);
|
||||
var modulus = ReadBigIntWithBits(reader);
|
||||
var inverseQ = ReadBigIntWithBits(reader);
|
||||
var q = ReadBigIntWithBits(reader);
|
||||
var p = ReadBigIntWithBits(reader);
|
||||
var exponent = ReadBigIntWithBits(keyReader);
|
||||
var d = ReadBigIntWithBits(keyReader);
|
||||
var modulus = ReadBigIntWithBits(keyReader);
|
||||
var inverseQ = ReadBigIntWithBits(keyReader);
|
||||
var q = ReadBigIntWithBits(keyReader);
|
||||
var p = ReadBigIntWithBits(keyReader);
|
||||
return new RsaKey(modulus, exponent, d, p, q, inverseQ);
|
||||
}
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace Renci.SshNet
|
||||
/// <param name="key">The key.</param>
|
||||
public PrivateKeyFile(Key key)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(key);
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
_key = key;
|
||||
_hostAlgorithms.Add(new KeyHostAlgorithm(key.ToString(), key));
|
||||
@@ -223,7 +223,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="fileName"/> is <see langword="null"/>.</exception>
|
||||
public PrivateKeyFile(string fileName, string? passPhrase, string? certificateFileName)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(fileName);
|
||||
ArgumentNullException.ThrowIfNull(fileName);
|
||||
|
||||
using (var keyFile = File.OpenRead(fileName))
|
||||
{
|
||||
@@ -263,7 +263,7 @@ namespace Renci.SshNet
|
||||
/// <param name="certificate">A certificate which certifies the private key.</param>
|
||||
public PrivateKeyFile(Stream privateKey, string? passPhrase, Stream? certificate)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(privateKey);
|
||||
ArgumentNullException.ThrowIfNull(privateKey);
|
||||
|
||||
Open(privateKey, passPhrase);
|
||||
|
||||
@@ -370,10 +370,8 @@ namespace Renci.SshNet
|
||||
if (_key is RsaKey rsaKey)
|
||||
{
|
||||
_hostAlgorithms.Add(new KeyHostAlgorithm("ssh-rsa", _key));
|
||||
#pragma warning disable CA2000 // Dispose objects before losing scope
|
||||
_hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-512", _key, new RsaDigitalSignature(rsaKey, HashAlgorithmName.SHA512)));
|
||||
_hostAlgorithms.Add(new KeyHostAlgorithm("rsa-sha2-256", _key, new RsaDigitalSignature(rsaKey, HashAlgorithmName.SHA256)));
|
||||
#pragma warning restore CA2000 // Dispose objects before losing scope
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -420,7 +418,6 @@ namespace Renci.SshNet
|
||||
|
||||
_hostAlgorithms.Insert(0, new CertificateHostAlgorithm("ssh-rsa-cert-v01@openssh.com", Key, Certificate));
|
||||
|
||||
#pragma warning disable CA2000 // Dispose objects before losing scope
|
||||
_hostAlgorithms.Insert(0, new CertificateHostAlgorithm(
|
||||
"rsa-sha2-256-cert-v01@openssh.com",
|
||||
Key,
|
||||
@@ -432,7 +429,6 @@ namespace Renci.SshNet
|
||||
Key,
|
||||
Certificate,
|
||||
new RsaDigitalSignature(rsaKey, HashAlgorithmName.SHA512)));
|
||||
#pragma warning restore CA2000 // Dispose objects before losing scope
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
/// <summary>
|
||||
@@ -52,7 +50,7 @@ namespace Renci.SshNet
|
||||
/// </example>
|
||||
public string Transform(string path)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
var transformed = new StringBuilder(path.Length);
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
/// <summary>
|
||||
@@ -23,7 +21,7 @@ namespace Renci.SshNet
|
||||
/// </remarks>
|
||||
public string Transform(string path)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
/// <summary>
|
||||
@@ -82,7 +80,7 @@ namespace Renci.SshNet
|
||||
/// </example>
|
||||
public string Transform(string path)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
// result is at least value and (likely) leading/trailing single-quotes
|
||||
var sb = new StringBuilder(path.Length + 2);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<AssemblyName>Renci.SshNet</AssemblyName>
|
||||
<Product>SSH.NET</Product>
|
||||
<AssemblyTitle>SSH.NET</AssemblyTitle>
|
||||
<TargetFrameworks>net462;netstandard2.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net462;netstandard2.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
@@ -116,7 +115,7 @@ namespace Renci.SshNet
|
||||
}
|
||||
set
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(value);
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
_remotePathTransformation = value;
|
||||
}
|
||||
@@ -152,7 +151,6 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="password"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid, or <paramref name="username"/> is <see langword="null"/> or contains only whitespace characters.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
|
||||
public ScpClient(string host, int port, string username, string password)
|
||||
: this(new PasswordConnectionInfo(host, port, username, password), ownsConnectionInfo: true)
|
||||
{
|
||||
@@ -181,7 +179,6 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="keyFiles"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid, -or- <paramref name="username"/> is <see langword="null"/> or contains only whitespace characters.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
|
||||
public ScpClient(string host, int port, string username, params IPrivateKeySource[] keyFiles)
|
||||
: this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), ownsConnectionInfo: true)
|
||||
{
|
||||
@@ -288,7 +285,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SshConnectionException">Client is not connected.</exception>
|
||||
public void Upload(FileInfo fileInfo, string path)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(fileInfo);
|
||||
ArgumentNullException.ThrowIfNull(fileInfo);
|
||||
|
||||
if (Session is null)
|
||||
{
|
||||
@@ -335,8 +332,8 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SshConnectionException">Client is not connected.</exception>
|
||||
public void Upload(DirectoryInfo directoryInfo, string path)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(directoryInfo);
|
||||
ThrowHelper.ThrowIfNullOrEmpty(path);
|
||||
ArgumentNullException.ThrowIfNull(directoryInfo);
|
||||
ArgumentException.ThrowIfNullOrEmpty(path);
|
||||
|
||||
if (Session is null)
|
||||
{
|
||||
@@ -378,8 +375,8 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SshConnectionException">Client is not connected.</exception>
|
||||
public void Download(string filename, FileInfo fileInfo)
|
||||
{
|
||||
ThrowHelper.ThrowIfNullOrEmpty(filename);
|
||||
ThrowHelper.ThrowIfNull(fileInfo);
|
||||
ArgumentException.ThrowIfNullOrEmpty(filename);
|
||||
ArgumentNullException.ThrowIfNull(fileInfo);
|
||||
|
||||
if (Session is null)
|
||||
{
|
||||
@@ -418,8 +415,8 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SshConnectionException">Client is not connected.</exception>
|
||||
public void Download(string directoryName, DirectoryInfo directoryInfo)
|
||||
{
|
||||
ThrowHelper.ThrowIfNullOrEmpty(directoryName);
|
||||
ThrowHelper.ThrowIfNull(directoryInfo);
|
||||
ArgumentException.ThrowIfNullOrEmpty(directoryName);
|
||||
ArgumentNullException.ThrowIfNull(directoryInfo);
|
||||
|
||||
if (Session is null)
|
||||
{
|
||||
@@ -458,8 +455,8 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SshConnectionException">Client is not connected.</exception>
|
||||
public void Download(string filename, Stream destination)
|
||||
{
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(filename);
|
||||
ThrowHelper.ThrowIfNull(destination);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(filename);
|
||||
ArgumentNullException.ThrowIfNull(destination);
|
||||
|
||||
if (Session is null)
|
||||
{
|
||||
@@ -675,11 +672,7 @@ namespace Renci.SshNet
|
||||
/// <param name="fileOrDirectory">The file or directory to upload.</param>
|
||||
private void UploadTimes(IChannelSession channel, Stream input, FileSystemInfo fileOrDirectory)
|
||||
{
|
||||
#if NET
|
||||
var zeroTime = DateTime.UnixEpoch;
|
||||
#else
|
||||
var zeroTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
#endif
|
||||
var modificationSeconds = (long)(fileOrDirectory.LastWriteTimeUtc - zeroTime).TotalSeconds;
|
||||
var accessSeconds = (long)(fileOrDirectory.LastAccessTimeUtc - zeroTime).TotalSeconds;
|
||||
SendData(channel, string.Format(CultureInfo.InvariantCulture, "T{0} 0 {1} 0\n", modificationSeconds, accessSeconds));
|
||||
@@ -856,11 +849,7 @@ namespace Renci.SshNet
|
||||
var mtime = long.Parse(match.Result("${mtime}"), CultureInfo.InvariantCulture);
|
||||
var atime = long.Parse(match.Result("${atime}"), CultureInfo.InvariantCulture);
|
||||
|
||||
#if NET
|
||||
var zeroTime = DateTime.UnixEpoch;
|
||||
#else
|
||||
var zeroTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
#endif
|
||||
modifiedTime = zeroTime.AddSeconds(mtime);
|
||||
accessedTime = zeroTime.AddSeconds(atime);
|
||||
continue;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Security
|
||||
@@ -228,7 +228,7 @@ namespace Renci.SshNet.Security
|
||||
{
|
||||
get
|
||||
{
|
||||
return Convert.ToBase64String(CryptoAbstraction.HashSHA256(CertificateAuthorityKey)).TrimEnd('=');
|
||||
return Convert.ToBase64String(SHA256.HashData(CertificateAuthorityKey)).TrimEnd('=');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
|
||||
|
||||
if (cipherMode != System.Security.Cryptography.CipherMode.ECB)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(iv);
|
||||
ArgumentNullException.ThrowIfNull(iv);
|
||||
|
||||
aes.IV = iv.Take(16);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is <see langword="null"/>.</exception>
|
||||
public ED25519DigitalSignature(ED25519Key key)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(key);
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
_key = key;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Renci.SshNet.Security
|
||||
/// <param name="publicKeyData">The encoded public key data.</param>
|
||||
public ED25519Key(SshKeyData publicKeyData)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(publicKeyData);
|
||||
ArgumentNullException.ThrowIfNull(publicKeyData);
|
||||
|
||||
if (publicKeyData.Name != "ssh-ed25519" || publicKeyData.Keys.Length != 1)
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is <see langword="null"/>.</exception>
|
||||
public EcdsaDigitalSignature(EcdsaKey key)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(key);
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
_key = key;
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ namespace Renci.SshNet.Security
|
||||
/// <param name="publicKeyData">The encoded public key data.</param>
|
||||
public EcdsaKey(SshKeyData publicKeyData)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(publicKeyData);
|
||||
ArgumentNullException.ThrowIfNull(publicKeyData);
|
||||
|
||||
if (!publicKeyData.Name.StartsWith("ecdsa-sha2-", StringComparison.Ordinal) || publicKeyData.Keys.Length != 2)
|
||||
{
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace Renci.SshNet.Security
|
||||
/// <param name="publicKeyData">The encoded public key data.</param>
|
||||
public RsaKey(SshKeyData publicKeyData)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(publicKeyData);
|
||||
ArgumentNullException.ThrowIfNull(publicKeyData);
|
||||
|
||||
if (publicKeyData.Name != "ssh-rsa" || publicKeyData.Keys.Length != 2)
|
||||
{
|
||||
@@ -159,7 +159,7 @@ namespace Renci.SshNet.Security
|
||||
/// <param name="privateKeyData">DER encoded private key data.</param>
|
||||
public RsaKey(byte[] privateKeyData)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(privateKeyData);
|
||||
ArgumentNullException.ThrowIfNull(privateKeyData);
|
||||
|
||||
var keyReader = new AsnReader(privateKeyData, AsnEncodingRules.DER);
|
||||
var sequenceReader = keyReader.ReadSequence();
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Security.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
@@ -21,7 +19,7 @@ namespace Renci.SshNet.Security.Cryptography
|
||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is <see langword="null"/>.</exception>
|
||||
protected SymmetricCipher(byte[] key)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(key);
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
Key = key;
|
||||
}
|
||||
|
||||
@@ -91,17 +91,17 @@ namespace Renci.SshNet.Security
|
||||
{
|
||||
_logger.LogTrace("[{SessionId}] Host key algorithm: we offer {WeOffer}",
|
||||
Session.SessionIdHex,
|
||||
session.ConnectionInfo.HostKeyAlgorithms.Keys.Join(","));
|
||||
string.Join(',', session.ConnectionInfo.HostKeyAlgorithms.Keys));
|
||||
|
||||
_logger.LogTrace("[{SessionId}] Host key algorithm: they offer {TheyOffer}",
|
||||
Session.SessionIdHex,
|
||||
message.ServerHostKeyAlgorithms.Join(","));
|
||||
string.Join(',', message.ServerHostKeyAlgorithms));
|
||||
}
|
||||
|
||||
if (hostKeyAlgorithmName is null)
|
||||
{
|
||||
throw new SshConnectionException(
|
||||
$"No matching host key algorithm (server offers {message.ServerHostKeyAlgorithms.Join(",")})",
|
||||
$"No matching host key algorithm (server offers {string.Join(',', message.ServerHostKeyAlgorithms)})",
|
||||
DisconnectReason.KeyExchangeFailed);
|
||||
}
|
||||
|
||||
@@ -118,17 +118,17 @@ namespace Renci.SshNet.Security
|
||||
{
|
||||
_logger.LogTrace("[{SessionId}] Encryption client to server: we offer {WeOffer}",
|
||||
Session.SessionIdHex,
|
||||
session.ConnectionInfo.Encryptions.Keys.Join(","));
|
||||
string.Join(',', session.ConnectionInfo.Encryptions.Keys));
|
||||
|
||||
_logger.LogTrace("[{SessionId}] Encryption client to server: they offer {TheyOffer}",
|
||||
Session.SessionIdHex,
|
||||
message.EncryptionAlgorithmsClientToServer.Join(","));
|
||||
string.Join(',', message.EncryptionAlgorithmsClientToServer));
|
||||
}
|
||||
|
||||
if (clientEncryptionAlgorithmName is null)
|
||||
{
|
||||
throw new SshConnectionException(
|
||||
$"No matching client encryption algorithm (server offers {message.EncryptionAlgorithmsClientToServer.Join(",")})",
|
||||
$"No matching client encryption algorithm (server offers {string.Join(',', message.EncryptionAlgorithmsClientToServer)})",
|
||||
DisconnectReason.KeyExchangeFailed);
|
||||
}
|
||||
|
||||
@@ -145,17 +145,17 @@ namespace Renci.SshNet.Security
|
||||
{
|
||||
_logger.LogTrace("[{SessionId}] Encryption server to client: we offer {WeOffer}",
|
||||
Session.SessionIdHex,
|
||||
session.ConnectionInfo.Encryptions.Keys.Join(","));
|
||||
string.Join(',', session.ConnectionInfo.Encryptions.Keys));
|
||||
|
||||
_logger.LogTrace("[{SessionId}] Encryption server to client: they offer {TheyOffer}",
|
||||
Session.SessionIdHex,
|
||||
message.EncryptionAlgorithmsServerToClient.Join(","));
|
||||
string.Join(',', message.EncryptionAlgorithmsServerToClient));
|
||||
}
|
||||
|
||||
if (serverDecryptionAlgorithmName is null)
|
||||
{
|
||||
throw new SshConnectionException(
|
||||
$"No matching server encryption algorithm (server offers {message.EncryptionAlgorithmsServerToClient.Join(",")})",
|
||||
$"No matching server encryption algorithm (server offers {string.Join(',', message.EncryptionAlgorithmsServerToClient)})",
|
||||
DisconnectReason.KeyExchangeFailed);
|
||||
}
|
||||
|
||||
@@ -174,17 +174,17 @@ namespace Renci.SshNet.Security
|
||||
{
|
||||
_logger.LogTrace("[{SessionId}] MAC client to server: we offer {WeOffer}",
|
||||
Session.SessionIdHex,
|
||||
session.ConnectionInfo.HmacAlgorithms.Keys.Join(","));
|
||||
string.Join(',', session.ConnectionInfo.HmacAlgorithms.Keys));
|
||||
|
||||
_logger.LogTrace("[{SessionId}] MAC client to server: they offer {TheyOffer}",
|
||||
Session.SessionIdHex,
|
||||
message.MacAlgorithmsClientToServer.Join(","));
|
||||
string.Join(',', message.MacAlgorithmsClientToServer));
|
||||
}
|
||||
|
||||
if (clientHmacAlgorithmName is null)
|
||||
{
|
||||
throw new SshConnectionException(
|
||||
$"No matching client MAC algorithm (server offers {message.MacAlgorithmsClientToServer.Join(",")})",
|
||||
$"No matching client MAC algorithm (server offers {string.Join(',', message.MacAlgorithmsClientToServer)})",
|
||||
DisconnectReason.KeyExchangeFailed);
|
||||
}
|
||||
|
||||
@@ -204,17 +204,17 @@ namespace Renci.SshNet.Security
|
||||
{
|
||||
_logger.LogTrace("[{SessionId}] MAC server to client: we offer {WeOffer}",
|
||||
Session.SessionIdHex,
|
||||
session.ConnectionInfo.HmacAlgorithms.Keys.Join(","));
|
||||
string.Join(',', session.ConnectionInfo.HmacAlgorithms.Keys));
|
||||
|
||||
_logger.LogTrace("[{SessionId}] MAC server to client: they offer {TheyOffer}",
|
||||
Session.SessionIdHex,
|
||||
message.MacAlgorithmsServerToClient.Join(","));
|
||||
string.Join(',', message.MacAlgorithmsServerToClient));
|
||||
}
|
||||
|
||||
if (serverHmacAlgorithmName is null)
|
||||
{
|
||||
throw new SshConnectionException(
|
||||
$"No matching server MAC algorithm (server offers {message.MacAlgorithmsServerToClient.Join(",")})",
|
||||
$"No matching server MAC algorithm (server offers {string.Join(',', message.MacAlgorithmsServerToClient)})",
|
||||
DisconnectReason.KeyExchangeFailed);
|
||||
}
|
||||
|
||||
@@ -232,17 +232,17 @@ namespace Renci.SshNet.Security
|
||||
{
|
||||
_logger.LogTrace("[{SessionId}] Compression client to server: we offer {WeOffer}",
|
||||
Session.SessionIdHex,
|
||||
session.ConnectionInfo.CompressionAlgorithms.Keys.Join(","));
|
||||
string.Join(',', session.ConnectionInfo.CompressionAlgorithms.Keys));
|
||||
|
||||
_logger.LogTrace("[{SessionId}] Compression client to server: they offer {TheyOffer}",
|
||||
Session.SessionIdHex,
|
||||
message.CompressionAlgorithmsClientToServer.Join(","));
|
||||
string.Join(',', message.CompressionAlgorithmsClientToServer));
|
||||
}
|
||||
|
||||
if (compressionAlgorithmName is null)
|
||||
{
|
||||
throw new SshConnectionException(
|
||||
$"No matching client compression algorithm (server offers {message.CompressionAlgorithmsClientToServer.Join(",")})",
|
||||
$"No matching client compression algorithm (server offers {string.Join(',', message.CompressionAlgorithmsClientToServer)})",
|
||||
DisconnectReason.KeyExchangeFailed);
|
||||
}
|
||||
|
||||
@@ -259,17 +259,17 @@ namespace Renci.SshNet.Security
|
||||
{
|
||||
_logger.LogTrace("[{SessionId}] Compression server to client: we offer {WeOffer}",
|
||||
Session.SessionIdHex,
|
||||
session.ConnectionInfo.CompressionAlgorithms.Keys.Join(","));
|
||||
string.Join(',', session.ConnectionInfo.CompressionAlgorithms.Keys));
|
||||
|
||||
_logger.LogTrace("[{SessionId}] Compression server to client: they offer {TheyOffer}",
|
||||
Session.SessionIdHex,
|
||||
message.CompressionAlgorithmsServerToClient.Join(","));
|
||||
string.Join(',', message.CompressionAlgorithmsServerToClient));
|
||||
}
|
||||
|
||||
if (decompressionAlgorithmName is null)
|
||||
{
|
||||
throw new SshConnectionException(
|
||||
$"No matching server compression algorithm (server offers {message.CompressionAlgorithmsServerToClient.Join(",")})",
|
||||
$"No matching server compression algorithm (server offers {string.Join(',', message.CompressionAlgorithmsServerToClient)})",
|
||||
DisconnectReason.KeyExchangeFailed);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
|
||||
namespace Renci.SshNet.Security
|
||||
@@ -53,9 +52,9 @@ namespace Renci.SshNet.Security
|
||||
DHParameters parameters,
|
||||
HashAlgorithmName hashAlgorithm)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(name);
|
||||
ThrowHelper.ThrowIfNull(parameters);
|
||||
ThrowHelper.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
|
||||
ArgumentNullException.ThrowIfNull(name);
|
||||
ArgumentNullException.ThrowIfNull(parameters);
|
||||
ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
|
||||
|
||||
Name = name;
|
||||
_dhParameters = parameters;
|
||||
|
||||
@@ -7,7 +7,6 @@ using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
|
||||
namespace Renci.SshNet.Security
|
||||
@@ -83,8 +82,8 @@ namespace Renci.SshNet.Security
|
||||
uint preferredGroupSize,
|
||||
uint maximumGroupSize)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(name);
|
||||
ThrowHelper.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
|
||||
ArgumentNullException.ThrowIfNull(name);
|
||||
ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm));
|
||||
|
||||
if (preferredGroupSize < minimumGroupSize || preferredGroupSize > maximumGroupSize)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Renci.SshNet.Abstractions;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Messages.Transport;
|
||||
|
||||
@@ -89,7 +90,7 @@ namespace Renci.SshNet.Security
|
||||
/// </returns>
|
||||
protected override byte[] Hash(byte[] hashData)
|
||||
{
|
||||
return CryptoAbstraction.HashSHA256(hashData);
|
||||
return SHA256.HashData(hashData);
|
||||
}
|
||||
|
||||
private void Session_KeyExchangeEcdhReplyMessageReceived(object sender, MessageEventArgs<KeyExchangeEcdhReplyMessage> e)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Org.BouncyCastle.Asn1.Sec;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Org.BouncyCastle.Asn1.Sec;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
|
||||
namespace Renci.SshNet.Security
|
||||
{
|
||||
@@ -59,7 +59,7 @@ namespace Renci.SshNet.Security
|
||||
/// </returns>
|
||||
protected override byte[] Hash(byte[] hashData)
|
||||
{
|
||||
return CryptoAbstraction.HashSHA256(hashData);
|
||||
return SHA256.HashData(hashData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Org.BouncyCastle.Asn1.Sec;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Org.BouncyCastle.Asn1.Sec;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
|
||||
namespace Renci.SshNet.Security
|
||||
{
|
||||
@@ -59,7 +59,7 @@ namespace Renci.SshNet.Security
|
||||
/// </returns>
|
||||
protected override byte[] Hash(byte[] hashData)
|
||||
{
|
||||
return CryptoAbstraction.HashSHA384(hashData);
|
||||
return SHA384.HashData(hashData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Org.BouncyCastle.Asn1.Sec;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Renci.SshNet.Abstractions;
|
||||
using Org.BouncyCastle.Asn1.Sec;
|
||||
using Org.BouncyCastle.Asn1.X9;
|
||||
|
||||
namespace Renci.SshNet.Security
|
||||
{
|
||||
@@ -59,7 +59,7 @@ namespace Renci.SshNet.Security
|
||||
/// </returns>
|
||||
protected override byte[] Hash(byte[] hashData)
|
||||
{
|
||||
return CryptoAbstraction.HashSHA512(hashData);
|
||||
return SHA512.HashData(hashData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.Crypto.Kems;
|
||||
@@ -72,7 +73,7 @@ namespace Renci.SshNet.Security
|
||||
/// </returns>
|
||||
protected override byte[] Hash(byte[] hashData)
|
||||
{
|
||||
return CryptoAbstraction.HashSHA256(hashData);
|
||||
return SHA256.HashData(hashData);
|
||||
}
|
||||
|
||||
private void Session_KeyExchangeHybridReplyMessageReceived(object sender, MessageEventArgs<KeyExchangeHybridReplyMessage> e)
|
||||
@@ -113,7 +114,7 @@ namespace Renci.SshNet.Security
|
||||
|
||||
var x25519Agreement = _impl.CalculateAgreement(serverExchangeValue.Take(_mlkemDecapsulator.EncapsulationLength, X25519PublicKeyParameters.KeySize));
|
||||
|
||||
SharedKey = CryptoAbstraction.HashSHA256(mlkemSecret.Concat(x25519Agreement));
|
||||
SharedKey = SHA256.HashData(mlkemSecret.Concat(x25519Agreement));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Pqc.Crypto.NtruPrime;
|
||||
@@ -70,7 +71,7 @@ namespace Renci.SshNet.Security
|
||||
/// </returns>
|
||||
protected override byte[] Hash(byte[] hashData)
|
||||
{
|
||||
return CryptoAbstraction.HashSHA512(hashData);
|
||||
return SHA512.HashData(hashData);
|
||||
}
|
||||
|
||||
private void Session_KeyExchangeEcdhReplyMessageReceived(object sender, MessageEventArgs<KeyExchangeEcdhReplyMessage> e)
|
||||
@@ -111,7 +112,7 @@ namespace Renci.SshNet.Security
|
||||
|
||||
var x25519Agreement = _impl.CalculateAgreement(serverExchangeValue.Take(_sntrup761Extractor.EncapsulationLength, X25519PublicKeyParameters.KeySize));
|
||||
|
||||
SharedKey = CryptoAbstraction.HashSHA512(sntrup761Secret.Concat(x25519Agreement));
|
||||
SharedKey = SHA512.HashData(sntrup761Secret.Concat(x25519Agreement));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,8 +85,8 @@ namespace Renci.SshNet
|
||||
/// <inheritdoc/>
|
||||
public IKeyExchange CreateKeyExchange(IDictionary<string, Func<IKeyExchange>> clientAlgorithms, string[] serverAlgorithms)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(clientAlgorithms);
|
||||
ThrowHelper.ThrowIfNull(serverAlgorithms);
|
||||
ArgumentNullException.ThrowIfNull(clientAlgorithms);
|
||||
ArgumentNullException.ThrowIfNull(serverAlgorithms);
|
||||
|
||||
// find an algorithm that is supported by both client and server
|
||||
var keyExchangeAlgorithmFactory = (from c in clientAlgorithms
|
||||
@@ -96,7 +96,7 @@ namespace Renci.SshNet
|
||||
|
||||
if (keyExchangeAlgorithmFactory is null)
|
||||
{
|
||||
throw new SshConnectionException($"No matching key exchange algorithm (server offers {serverAlgorithms.Join(",")})", DisconnectReason.KeyExchangeFailed);
|
||||
throw new SshConnectionException($"No matching key exchange algorithm (server offers {string.Join(',', serverAlgorithms)})", DisconnectReason.KeyExchangeFailed);
|
||||
}
|
||||
|
||||
return keyExchangeAlgorithmFactory();
|
||||
@@ -168,8 +168,8 @@ namespace Renci.SshNet
|
||||
/// <exception cref="NotSupportedException">The <see cref="IConnectionInfo.ProxyType"/> value of <paramref name="connectionInfo"/> is not supported.</exception>
|
||||
public IConnector CreateConnector(IConnectionInfo connectionInfo, ISocketFactory socketFactory)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(connectionInfo);
|
||||
ThrowHelper.ThrowIfNull(socketFactory);
|
||||
ArgumentNullException.ThrowIfNull(connectionInfo);
|
||||
ArgumentNullException.ThrowIfNull(socketFactory);
|
||||
|
||||
var loggerFactory = connectionInfo.LoggerFactory ?? SshNetLoggingConfiguration.LoggerFactory;
|
||||
|
||||
|
||||
+11
-41
@@ -5,9 +5,6 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography;
|
||||
#if !NET
|
||||
using System.Text;
|
||||
#endif
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -298,7 +295,7 @@ namespace Renci.SshNet
|
||||
private set
|
||||
{
|
||||
_sessionId = value;
|
||||
SessionIdHex = ToHex(value);
|
||||
SessionIdHex = value == null ? null : Convert.ToHexString(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,9 +542,9 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="socketFactory"/> is <see langword="null"/>.</exception>
|
||||
internal Session(ConnectionInfo connectionInfo, IServiceFactory serviceFactory, ISocketFactory socketFactory)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(connectionInfo);
|
||||
ThrowHelper.ThrowIfNull(serviceFactory);
|
||||
ThrowHelper.ThrowIfNull(socketFactory);
|
||||
ArgumentNullException.ThrowIfNull(connectionInfo);
|
||||
ArgumentNullException.ThrowIfNull(serviceFactory);
|
||||
ArgumentNullException.ThrowIfNull(socketFactory);
|
||||
|
||||
ConnectionInfo = connectionInfo;
|
||||
SessionLoggerFactory = connectionInfo.LoggerFactory ?? SshNetLoggingConfiguration.LoggerFactory;
|
||||
@@ -925,7 +922,7 @@ namespace Renci.SshNet
|
||||
/// </returns>
|
||||
private WaitResult TryWait(WaitHandle waitHandle, TimeSpan timeout, out Exception exception)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(waitHandle);
|
||||
ArgumentNullException.ThrowIfNull(waitHandle);
|
||||
|
||||
var waitHandles = new[]
|
||||
{
|
||||
@@ -987,7 +984,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SocketException">A socket error was signaled while receiving messages from the server.</exception>
|
||||
internal void WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(waitHandle);
|
||||
ArgumentNullException.ThrowIfNull(waitHandle);
|
||||
|
||||
var waitHandles = new[]
|
||||
{
|
||||
@@ -1546,17 +1543,11 @@ namespace Renci.SshNet
|
||||
disposableClientCipher.Dispose();
|
||||
}
|
||||
|
||||
if (_serverMac != null)
|
||||
{
|
||||
_serverMac.Dispose();
|
||||
_serverMac = null;
|
||||
}
|
||||
_serverMac?.Dispose();
|
||||
_serverMac = null;
|
||||
|
||||
if (_clientMac != null)
|
||||
{
|
||||
_clientMac.Dispose();
|
||||
_clientMac = null;
|
||||
}
|
||||
_clientMac?.Dispose();
|
||||
_clientMac = null;
|
||||
|
||||
// Update negotiated algorithms
|
||||
_serverCipher = _keyExchange.CreateServerCipher(out _serverAead);
|
||||
@@ -1574,7 +1565,7 @@ namespace Renci.SshNet
|
||||
{
|
||||
System.IO.File.AppendAllText(
|
||||
path,
|
||||
$"{ToHex(ClientInitMessage.Cookie)} SHARED_SECRET {ToHex(kex.SharedKey)}{Environment.NewLine}");
|
||||
$"{Convert.ToHexString(ClientInitMessage.Cookie)} SHARED_SECRET {Convert.ToHexString(kex.SharedKey)}{Environment.NewLine}");
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1843,27 +1834,6 @@ namespace Renci.SshNet
|
||||
return message;
|
||||
}
|
||||
|
||||
private static string ToHex(byte[] bytes)
|
||||
{
|
||||
if (bytes is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
#if NET
|
||||
return Convert.ToHexString(bytes);
|
||||
#else
|
||||
var builder = new StringBuilder(bytes.Length * 2);
|
||||
|
||||
foreach (var b in bytes)
|
||||
{
|
||||
builder.Append(b.ToString("X2"));
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a blocking read on the socket until <paramref name="length"/> bytes are received.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
using Renci.SshNet.Sftp.Responses;
|
||||
|
||||
namespace Renci.SshNet.Sftp.Requests
|
||||
@@ -44,7 +43,7 @@ namespace Renci.SshNet.Sftp.Requests
|
||||
public SftpRealPathRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action<SftpNameResponse> nameAction, Action<SftpStatusResponse> statusAction)
|
||||
: base(protocolVersion, requestId, statusAction)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(nameAction);
|
||||
ArgumentNullException.ThrowIfNull(nameAction);
|
||||
|
||||
Encoding = encoding;
|
||||
Path = path;
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace Renci.SshNet.Sftp
|
||||
throw new SshConnectionException("Client not connected.");
|
||||
}
|
||||
|
||||
ThrowHelper.ThrowIfNull(attributes);
|
||||
ThrowHelper.ThrowIfNull(fullName);
|
||||
ArgumentNullException.ThrowIfNull(attributes);
|
||||
ArgumentNullException.ThrowIfNull(fullName);
|
||||
|
||||
_sftpSession = sftpSession;
|
||||
Attributes = attributes;
|
||||
@@ -485,7 +485,7 @@ namespace Renci.SshNet.Sftp
|
||||
/// <exception cref="ArgumentNullException"><paramref name="destFileName"/> is <see langword="null"/>.</exception>
|
||||
public void MoveTo(string destFileName)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(destFileName);
|
||||
ArgumentNullException.ThrowIfNull(destFileName);
|
||||
|
||||
_sftpSession.RequestRename(FullName, destFileName);
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ namespace Renci.SshNet.Sftp
|
||||
{
|
||||
Debug.Assert(isAsync || cancellationToken == default);
|
||||
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
if (bufferSize <= 0)
|
||||
{
|
||||
@@ -332,7 +332,7 @@ namespace Renci.SshNet.Sftp
|
||||
/// <inheritdoc/>
|
||||
public override void Flush()
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_disposed, this);
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
var writeLength = _writeBuffer.ActiveLength;
|
||||
|
||||
@@ -363,7 +363,7 @@ namespace Renci.SshNet.Sftp
|
||||
/// <inheritdoc/>
|
||||
public override async Task FlushAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_disposed, this);
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
var writeLength = _writeBuffer.ActiveLength;
|
||||
|
||||
@@ -662,7 +662,7 @@ namespace Renci.SshNet.Sftp
|
||||
/// <inheritdoc/>
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
ThrowHelper.ThrowIfNegative(value);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(value);
|
||||
ThrowIfNotWriteable();
|
||||
ThrowIfNotSeekable();
|
||||
|
||||
@@ -755,7 +755,7 @@ namespace Renci.SshNet.Sftp
|
||||
{
|
||||
if (!CanSeek)
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_disposed, this);
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
Throw();
|
||||
}
|
||||
|
||||
@@ -769,7 +769,7 @@ namespace Renci.SshNet.Sftp
|
||||
{
|
||||
if (!CanWrite)
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_disposed, this);
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
Throw();
|
||||
}
|
||||
|
||||
@@ -783,7 +783,7 @@ namespace Renci.SshNet.Sftp
|
||||
{
|
||||
if (!CanRead)
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_disposed, this);
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
Throw();
|
||||
}
|
||||
|
||||
|
||||
@@ -113,22 +113,14 @@ namespace Renci.SshNet.Sftp
|
||||
if (fullPath.EndsWith("/.", StringComparison.OrdinalIgnoreCase) ||
|
||||
fullPath.EndsWith("/..", StringComparison.OrdinalIgnoreCase) ||
|
||||
fullPath.Equals("/", StringComparison.OrdinalIgnoreCase) ||
|
||||
#if NET
|
||||
fullPath.IndexOf('/', StringComparison.OrdinalIgnoreCase) < 0)
|
||||
#else
|
||||
fullPath.IndexOf('/') < 0)
|
||||
#endif
|
||||
{
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
var pathParts = fullPath.Split('/');
|
||||
|
||||
#if NET
|
||||
var partialFullPath = string.Join('/', pathParts, 0, pathParts.Length - 1);
|
||||
#else
|
||||
var partialFullPath = string.Join("/", pathParts, 0, pathParts.Length - 1);
|
||||
#endif
|
||||
|
||||
if (string.IsNullOrEmpty(partialFullPath))
|
||||
{
|
||||
|
||||
@@ -3,7 +3,6 @@ using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -202,7 +201,6 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="password"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid. <para>-or-</para> <paramref name="username"/> is <see langword="null"/> or contains only whitespace characters.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
|
||||
public SftpClient(string host, int port, string username, string password)
|
||||
: this(new PasswordConnectionInfo(host, port, username, password), ownsConnectionInfo: true)
|
||||
{
|
||||
@@ -231,7 +229,6 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="keyFiles"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid. <para>-or-</para> <paramref name="username"/> is <see langword="null"/> or contains only whitespace characters.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
|
||||
public SftpClient(string host, int port, string username, params IPrivateKeySource[] keyFiles)
|
||||
: this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), ownsConnectionInfo: true)
|
||||
{
|
||||
@@ -299,7 +296,7 @@ namespace Renci.SshNet
|
||||
public void ChangeDirectory(string path)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -324,7 +321,7 @@ namespace Renci.SshNet
|
||||
public Task ChangeDirectoryAsync(string path, CancellationToken cancellationToken = default)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -365,7 +362,7 @@ namespace Renci.SshNet
|
||||
public void CreateDirectory(string path)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -391,7 +388,7 @@ namespace Renci.SshNet
|
||||
public async Task CreateDirectoryAsync(string path, CancellationToken cancellationToken = default)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -416,7 +413,7 @@ namespace Renci.SshNet
|
||||
public void DeleteDirectory(string path)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -432,7 +429,7 @@ namespace Renci.SshNet
|
||||
public async Task DeleteDirectoryAsync(string path, CancellationToken cancellationToken = default)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -459,7 +456,7 @@ namespace Renci.SshNet
|
||||
public void DeleteFile(string path)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -475,7 +472,7 @@ namespace Renci.SshNet
|
||||
public async Task DeleteFileAsync(string path, CancellationToken cancellationToken)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -517,8 +514,8 @@ namespace Renci.SshNet
|
||||
public void RenameFile(string oldPath, string newPath, bool isPosix)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNull(oldPath);
|
||||
ThrowHelper.ThrowIfNull(newPath);
|
||||
ArgumentNullException.ThrowIfNull(oldPath);
|
||||
ArgumentNullException.ThrowIfNull(newPath);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -554,8 +551,8 @@ namespace Renci.SshNet
|
||||
public async Task RenameFileAsync(string oldPath, string newPath, CancellationToken cancellationToken)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNull(oldPath);
|
||||
ThrowHelper.ThrowIfNull(newPath);
|
||||
ArgumentNullException.ThrowIfNull(oldPath);
|
||||
ArgumentNullException.ThrowIfNull(newPath);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -582,8 +579,8 @@ namespace Renci.SshNet
|
||||
public void SymbolicLink(string path, string linkPath)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(linkPath);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(linkPath);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -634,7 +631,7 @@ namespace Renci.SshNet
|
||||
public async IAsyncEnumerable<ISftpFile> ListDirectoryAsync(string path, [EnumeratorCancellation] CancellationToken cancellationToken)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -739,7 +736,7 @@ namespace Renci.SshNet
|
||||
public ISftpFile Get(string path)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -769,7 +766,7 @@ namespace Renci.SshNet
|
||||
public async Task<ISftpFile> GetAsync(string path, CancellationToken cancellationToken)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -800,7 +797,7 @@ namespace Renci.SshNet
|
||||
public bool Exists(string path)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -856,7 +853,7 @@ namespace Renci.SshNet
|
||||
public async Task<bool> ExistsAsync(string path, CancellationToken cancellationToken = default)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -900,8 +897,8 @@ namespace Renci.SshNet
|
||||
/// <inheritdoc />
|
||||
public void DownloadFile(string path, Stream output, Action<ulong>? downloadCallback = null)
|
||||
{
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ThrowHelper.ThrowIfNull(output);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentNullException.ThrowIfNull(output);
|
||||
CheckDisposed();
|
||||
|
||||
InternalDownloadFile(
|
||||
@@ -916,8 +913,8 @@ namespace Renci.SshNet
|
||||
/// <inheritdoc />
|
||||
public Task DownloadFileAsync(string path, Stream output, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ThrowHelper.ThrowIfNull(output);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentNullException.ThrowIfNull(output);
|
||||
CheckDisposed();
|
||||
|
||||
return InternalDownloadFile(
|
||||
@@ -993,8 +990,8 @@ namespace Renci.SshNet
|
||||
/// </remarks>
|
||||
public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback? asyncCallback, object? state, Action<ulong>? downloadCallback = null)
|
||||
{
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ThrowHelper.ThrowIfNull(output);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentNullException.ThrowIfNull(output);
|
||||
CheckDisposed();
|
||||
|
||||
var asyncResult = new SftpDownloadAsyncResult(asyncCallback, state);
|
||||
@@ -1053,8 +1050,8 @@ namespace Renci.SshNet
|
||||
/// <inheritdoc/>
|
||||
public void UploadFile(Stream input, string path, bool canOverride, Action<ulong>? uploadCallback = null)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(input);
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentNullException.ThrowIfNull(input);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
CheckDisposed();
|
||||
|
||||
var flags = Flags.Write | Flags.Truncate;
|
||||
@@ -1081,8 +1078,8 @@ namespace Renci.SshNet
|
||||
/// <inheritdoc />
|
||||
public Task UploadFileAsync(Stream input, string path, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(input);
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentNullException.ThrowIfNull(input);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
CheckDisposed();
|
||||
|
||||
return InternalUploadFile(
|
||||
@@ -1207,8 +1204,8 @@ namespace Renci.SshNet
|
||||
/// </remarks>
|
||||
public IAsyncResult BeginUploadFile(Stream input, string path, bool canOverride, AsyncCallback? asyncCallback, object? state, Action<ulong>? uploadCallback = null)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(input);
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(path);
|
||||
ArgumentNullException.ThrowIfNull(input);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(path);
|
||||
CheckDisposed();
|
||||
|
||||
var flags = Flags.Write | Flags.Truncate;
|
||||
@@ -1283,7 +1280,7 @@ namespace Renci.SshNet
|
||||
public SftpFileSystemInformation GetStatus(string path)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -1310,7 +1307,7 @@ namespace Renci.SshNet
|
||||
public async Task<SftpFileSystemInformation> GetStatusAsync(string path, CancellationToken cancellationToken)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -1340,7 +1337,7 @@ namespace Renci.SshNet
|
||||
public void AppendAllLines(string path, IEnumerable<string> contents)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNull(contents);
|
||||
ArgumentNullException.ThrowIfNull(contents);
|
||||
|
||||
using (var stream = AppendText(path))
|
||||
{
|
||||
@@ -1364,7 +1361,7 @@ namespace Renci.SshNet
|
||||
public void AppendAllLines(string path, IEnumerable<string> contents, Encoding encoding)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNull(contents);
|
||||
ArgumentNullException.ThrowIfNull(contents);
|
||||
|
||||
using (var stream = AppendText(path, encoding))
|
||||
{
|
||||
@@ -1447,7 +1444,7 @@ namespace Renci.SshNet
|
||||
public StreamWriter AppendText(string path, Encoding encoding)
|
||||
{
|
||||
CheckDisposed();
|
||||
ThrowHelper.ThrowIfNull(encoding);
|
||||
ArgumentNullException.ThrowIfNull(encoding);
|
||||
|
||||
return new StreamWriter(Open(path, FileMode.Append, FileAccess.Write), encoding);
|
||||
}
|
||||
@@ -1832,7 +1829,7 @@ namespace Renci.SshNet
|
||||
public IEnumerable<string> ReadLines(string path, Encoding encoding)
|
||||
{
|
||||
// We allow this usage exception to throw eagerly...
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
// ... but other exceptions will throw lazily i.e. inside the state machine created
|
||||
// by yield. We could choose to open the file eagerly as well in order to throw
|
||||
@@ -1905,7 +1902,7 @@ namespace Renci.SshNet
|
||||
/// <inheritdoc/>
|
||||
public void WriteAllBytes(string path, byte[] bytes)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(bytes);
|
||||
ArgumentNullException.ThrowIfNull(bytes);
|
||||
|
||||
UploadFile(new MemoryStream(bytes), path);
|
||||
}
|
||||
@@ -2051,8 +2048,8 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SshException">If a problem occurs while copying the file.</exception>
|
||||
public IEnumerable<FileInfo> SynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(sourcePath);
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(destinationPath);
|
||||
ArgumentNullException.ThrowIfNull(sourcePath);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(destinationPath);
|
||||
|
||||
return InternalSynchronizeDirectories(sourcePath, destinationPath, searchPattern, asyncResult: null);
|
||||
}
|
||||
@@ -2073,9 +2070,9 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SshException">If a problem occurs while copying the file.</exception>
|
||||
public IAsyncResult BeginSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, AsyncCallback? asyncCallback, object? state)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(sourcePath);
|
||||
ThrowHelper.ThrowIfNullOrWhiteSpace(destinationPath);
|
||||
ThrowHelper.ThrowIfNull(searchPattern);
|
||||
ArgumentNullException.ThrowIfNull(sourcePath);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(destinationPath);
|
||||
ArgumentNullException.ThrowIfNull(searchPattern);
|
||||
|
||||
var asyncResult = new SftpSynchronizeDirectoriesAsyncResult(asyncCallback, state);
|
||||
|
||||
@@ -2175,6 +2172,7 @@ namespace Renci.SshNet
|
||||
{
|
||||
using (var file = File.OpenRead(localFile.FullName))
|
||||
{
|
||||
#pragma warning disable CA2025 // Do not pass 'IDisposable' instances into unawaited tasks
|
||||
InternalUploadFile(
|
||||
file,
|
||||
remoteFileName,
|
||||
@@ -2183,6 +2181,7 @@ namespace Renci.SshNet
|
||||
uploadCallback: null,
|
||||
isAsync: false,
|
||||
CancellationToken.None).GetAwaiter().GetResult();
|
||||
#pragma warning restore CA2025 // Do not pass 'IDisposable' instances into unawaited tasks
|
||||
}
|
||||
|
||||
uploadedFiles.Add(localFile);
|
||||
@@ -2218,7 +2217,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SshConnectionException">Client not connected.</exception>
|
||||
private List<ISftpFile> InternalListDirectory(string path, SftpListDirectoryAsyncResult? asyncResult, Action<int>? listCallback)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(path);
|
||||
ArgumentNullException.ThrowIfNull(path);
|
||||
|
||||
if (_sftpSession is null)
|
||||
{
|
||||
@@ -2270,7 +2269,7 @@ namespace Renci.SshNet
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma warning disable S6966 // Awaitable method should be used
|
||||
#pragma warning disable CA1849 // Call async methods when in an async method
|
||||
private async Task InternalDownloadFile(
|
||||
string path,
|
||||
Stream output,
|
||||
@@ -2385,9 +2384,7 @@ namespace Renci.SshNet
|
||||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore S6966 // Awaitable method should be used
|
||||
|
||||
#pragma warning disable S6966 // Awaitable method should be used
|
||||
private async Task InternalUploadFile(
|
||||
Stream input,
|
||||
string path,
|
||||
@@ -2526,7 +2523,7 @@ namespace Renci.SshNet
|
||||
_sftpSession.RequestClose(handle);
|
||||
}
|
||||
}
|
||||
#pragma warning restore S6966 // Awaitable method should be used
|
||||
#pragma warning restore CA1849 // Call async methods when in an async method
|
||||
|
||||
/// <summary>
|
||||
/// Called when client is connected to the server.
|
||||
|
||||
@@ -215,7 +215,7 @@ namespace Renci.SshNet
|
||||
/// <inheritdoc/>
|
||||
public override void Flush()
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_disposed, this);
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
if (_writeBuffer.ActiveLength > 0)
|
||||
{
|
||||
@@ -295,7 +295,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ObjectDisposedException">The stream is closed.</exception>
|
||||
public void ChangeWindowSize(uint columns, uint rows, uint width, uint height)
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_disposed, this);
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
_channel.SendWindowChangeRequest(columns, rows, width, height);
|
||||
}
|
||||
@@ -864,7 +864,7 @@ namespace Renci.SshNet
|
||||
private void Write(ReadOnlySpan<byte> buffer)
|
||||
#endif
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_disposed, this);
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
while (!buffer.IsEmpty)
|
||||
{
|
||||
@@ -909,7 +909,7 @@ namespace Renci.SshNet
|
||||
private async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken)
|
||||
#endif
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_disposed, this);
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
while (!buffer.IsEmpty)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
@@ -58,9 +57,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid, or <paramref name="username"/> is <see langword="null"/> or contains only whitespace characters.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
|
||||
public SshClient(string host, int port, string username, string password)
|
||||
#pragma warning disable CA2000 // Dispose objects before losing scope
|
||||
: this(new PasswordConnectionInfo(host, port, username, password), ownsConnectionInfo: true)
|
||||
#pragma warning restore CA2000 // Dispose objects before losing scope
|
||||
{
|
||||
}
|
||||
|
||||
@@ -87,7 +84,6 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="keyFiles"/> is <see langword="null"/>.</exception>
|
||||
/// <exception cref="ArgumentException"><paramref name="host"/> is invalid, -or- <paramref name="username"/> is <see langword="null"/> or contains only whitespace characters.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
|
||||
public SshClient(string host, int port, string username, params IPrivateKeySource[] keyFiles)
|
||||
: this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), ownsConnectionInfo: true)
|
||||
{
|
||||
@@ -155,7 +151,7 @@ namespace Renci.SshNet
|
||||
/// <inheritdoc />
|
||||
public void AddForwardedPort(ForwardedPort port)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(port);
|
||||
ArgumentNullException.ThrowIfNull(port);
|
||||
|
||||
EnsureSessionIsOpen();
|
||||
|
||||
@@ -166,7 +162,7 @@ namespace Renci.SshNet
|
||||
/// <inheritdoc />
|
||||
public void RemoveForwardedPort(ForwardedPort port)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(port);
|
||||
ArgumentNullException.ThrowIfNull(port);
|
||||
|
||||
// Stop port forwarding before removing it
|
||||
port.Stop();
|
||||
@@ -325,11 +321,8 @@ namespace Renci.SshNet
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (_inputStream != null)
|
||||
{
|
||||
_inputStream.Dispose();
|
||||
_inputStream = null;
|
||||
}
|
||||
_inputStream?.Dispose();
|
||||
_inputStream = null;
|
||||
|
||||
_isDisposed = true;
|
||||
}
|
||||
|
||||
@@ -214,9 +214,9 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException">Either <paramref name="session"/>, <paramref name="commandText"/> is <see langword="null"/>.</exception>
|
||||
internal SshCommand(ISession session, string commandText, Encoding encoding)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(session);
|
||||
ThrowHelper.ThrowIfNull(commandText);
|
||||
ThrowHelper.ThrowIfNull(encoding);
|
||||
ArgumentNullException.ThrowIfNull(session);
|
||||
ArgumentNullException.ThrowIfNull(commandText);
|
||||
ArgumentNullException.ThrowIfNull(encoding);
|
||||
|
||||
_session = session;
|
||||
CommandText = commandText;
|
||||
@@ -244,7 +244,7 @@ namespace Renci.SshNet
|
||||
#pragma warning disable CA1849 // Call async methods when in an async method; PipeStream.DisposeAsync would complete synchronously anyway.
|
||||
public Task ExecuteAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_isDisposed, this);
|
||||
ObjectDisposedException.ThrowIf(_isDisposed, this);
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
@@ -385,7 +385,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SshOperationTimeoutException">Operation has timed out.</exception>
|
||||
public IAsyncResult BeginExecute(string commandText, AsyncCallback? callback, object? state)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(commandText);
|
||||
ArgumentNullException.ThrowIfNull(commandText);
|
||||
|
||||
CommandText = commandText;
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace Renci.SshNet
|
||||
|
||||
public void EnableAndActivateMessage(string messageName)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(messageName);
|
||||
ArgumentNullException.ThrowIfNull(messageName);
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
@@ -208,7 +208,7 @@ namespace Renci.SshNet
|
||||
|
||||
public void DisableAndDeactivateMessage(string messageName)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(messageName);
|
||||
ArgumentNullException.ThrowIfNull(messageName);
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
/// <summary>
|
||||
@@ -19,7 +19,7 @@ namespace Renci.SshNet
|
||||
/// <param name="loggerFactory">The logger factory.</param>
|
||||
public static void InitializeLogging(ILoggerFactory loggerFactory)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(loggerFactory);
|
||||
ArgumentNullException.ThrowIfNull(loggerFactory);
|
||||
LoggerFactory = loggerFactory;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace Renci.SshNet
|
||||
{
|
||||
get
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_isDisposed, this);
|
||||
ObjectDisposedException.ThrowIf(_isDisposed, this);
|
||||
|
||||
return _channel;
|
||||
}
|
||||
@@ -89,8 +89,8 @@ namespace Renci.SshNet
|
||||
/// <exception cref="ArgumentNullException"><paramref name="session" /> or <paramref name="subsystemName" /> is <see langword="null"/>.</exception>
|
||||
protected SubsystemSession(ISession session, string subsystemName, int operationTimeout)
|
||||
{
|
||||
ThrowHelper.ThrowIfNull(session);
|
||||
ThrowHelper.ThrowIfNull(subsystemName);
|
||||
ArgumentNullException.ThrowIfNull(session);
|
||||
ArgumentNullException.ThrowIfNull(subsystemName);
|
||||
|
||||
_session = session;
|
||||
_subsystemName = subsystemName;
|
||||
@@ -106,7 +106,7 @@ namespace Renci.SshNet
|
||||
/// <exception cref="SshException">The channel session could not be opened, or the subsystem could not be executed.</exception>
|
||||
public void Connect()
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_isDisposed, this);
|
||||
ObjectDisposedException.ThrowIf(_isDisposed, this);
|
||||
|
||||
if (IsOpen)
|
||||
{
|
||||
@@ -166,7 +166,7 @@ namespace Renci.SshNet
|
||||
/// <param name="data">The data to be sent.</param>
|
||||
public void SendData(byte[] data)
|
||||
{
|
||||
ThrowHelper.ThrowObjectDisposedIf(_isDisposed, this);
|
||||
ObjectDisposedException.ThrowIf(_isDisposed, this);
|
||||
EnsureSessionIsOpen();
|
||||
|
||||
_channel.SendData(data);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Renci.SshNet.AotCompatibilityTestApp
|
||||
{
|
||||
public static class Program
|
||||
internal static class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<PublishAot>true</PublishAot>
|
||||
<SelfContained>true</SelfContained>
|
||||
<TrimmerSingleWarn>false</TrimmerSingleWarn>
|
||||
|
||||
@@ -74,10 +74,6 @@ dotnet_diagnostic.MA0026.severity = silent
|
||||
|
||||
#### .NET Compiler Platform analysers rules ####
|
||||
|
||||
# CA2000: Dispose objects before losing scope
|
||||
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2000
|
||||
dotnet_diagnostic.CA2000.severity = silent
|
||||
|
||||
# IDE0046: Use conditional expression for return
|
||||
# https://learn.microsoft.com/en-ca/dotnet/fundamentals/code-analysis/style-rules/ide0046
|
||||
dotnet_diagnostic.IDE0046.severity = silent
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user