Skip to content

Password Authentication - System.ArgumentException: data #1217

New issue

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

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

Already on GitHub? Sign in to your account

Closed
okarpov opened this issue Oct 17, 2023 · 18 comments
Closed

Password Authentication - System.ArgumentException: data #1217

okarpov opened this issue Oct 17, 2023 · 18 comments

Comments

@okarpov
Copy link

okarpov commented Oct 17, 2023

This is with the latest nuget package

System.ArgumentException: data
at Renci.SshNet.Security.Cryptography.BlockCipher.Encrypt(Byte[] input, Int32 offset, Int32 length)
at Renci.SshNet.Session.SendMessage(Message message)
at Renci.SshNet.PasswordAuthenticationMethod.Authenticate(Session session)
at Renci.SshNet.ClientAuthentication.TryAuthenticate(ISession session, AuthenticationState authenticationState, String[] allowedAuthenticationMethods, SshAuthenticationException& authenticationException)
at Renci.SshNet.ClientAuthentication.Authenticate(IConnectionInfoInternal connectionInfo, ISession session)
at Renci.SshNet.ConnectionInfo.Authenticate(ISession session, IServiceFactory serviceFactory)
at Renci.SshNet.Session.ConnectAsync(CancellationToken cancellationToken)
at Renci.SshNet.BaseClient.CreateAndConnectSessionAsync(CancellationToken cancellationToken)
at Renci.SshNet.BaseClient.ConnectAsync(CancellationToken cancellationToken)

@WojciechNagorski
Copy link
Collaborator

@okarpov We need a description of the context of what you want do do.
What version of .NET do you use?
Can you provide the source code or mini repro?

@okarpov
Copy link
Author

okarpov commented Oct 17, 2023

This is connecting to VPS via SSH using username and password.
Code runs in multi-task scenario under .Net 8.0 + Windows 11

no code to reproduce because of this error is not constant.

@WojciechNagorski
Copy link
Collaborator

@okarpov You have to provide more detail or help as to reproduce the problem, if not I going to close this issue.
Can you describe the environment? More information about SSH server, version and what kind of server.

What do you mean by "multi-task", async code or threads. You can prepare a small console application that simulates what you do with this tasks.

@Rob-Hague
Copy link
Collaborator

Seemingly related to #805

@WojciechNagorski
Copy link
Collaborator

We can merge #818 but this will not fix the problem. This is simply adding a better error message.

@okarpov
Copy link
Author

okarpov commented Oct 17, 2023

Seemingly related to #805

yes, seems so

so this is simplified version of my code which works with +1000 Sftp and Ssh connections.
It connects to Ubuntu Server VPSs with from 20.04 to 22.04 versions.

runThread = new Thread(async () =>
{
    foreach (var vps in vpss)
    {
        Task ot = Task.Run(async () =>
        {
            Renci.SshNet.ConnectionInfo con = new Renci.SshNet.ConnectionInfo(vps.IP, vps.SSHPort, vps.UserName,
                    new PasswordAuthenticationMethod(vps.UserName, vps.Password),
                        new PrivateKeyAuthenticationMethod("rsa.key"));

                vps.SFTP = new SftpClient(con);
                vps.SFTP.HostKeyReceived += (sender, e) =>
                {
                    e.CanTrust = true;
                };

                var sftptask = vps.SFTP.ConnectAsync(CancellationToken.None);
                    using (FileStream fs = new FileStream(Path.GetFullPath($"{_workspace}\\Data\\{vps.IP}.zip"), FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        await sftptask.ConfigureAwait(false);
                        vps.SFTP.UploadFile(fs, $"/home/{Path.GetFileName(fs.Name)}", true,
                        (u) =>
                        {
                            vps.Log = $"Uploading {fs.Name}: " + u + Environment.NewLine;
                        });
                    }

            vps.SSH = new SshClient(con);

            vps.SSH.HostKeyReceived += (sender, e) =>
            {
                e.CanTrust = true;
            };
            var sshc = vps.SSH.ConnectAsync(CancellationToken.None);
            await sshc.ConfigureAwait(false);
            var cmd = vps.SSH.CreateCommand(ssh);

            var ires = cmd.BeginExecute();
            string res = cmd.EndExecute(ires);
        }
    }
});

@Rob-Hague
Copy link
Collaborator

Maybe it is a race between

var paddingMultiplier = _clientCipher is null ? (byte) 8 : Math.Max((byte) 8, _serverCipher.MinimumSize);

and

_clientCipher = _keyExchange.CreateClientCipher();

@okarpov
Copy link
Author

okarpov commented Oct 17, 2023

Maybe it is a race between

var paddingMultiplier = _clientCipher is null ? (byte) 8 : Math.Max((byte) 8, _serverCipher.MinimumSize);

and

_clientCipher = _keyExchange.CreateClientCipher();

_clientCipher is the instance field so i do not think so.

@okarpov
Copy link
Author

okarpov commented Oct 17, 2023

also, the stack trace mentiones Renci.SshNet.Security.Cryptography.BlockCipher.Encrypt

@Rob-Hague
Copy link
Collaborator

looks like this

Correct, and my thinking is that the length parameter is incorrect because the paddingMultiplier could be a different value depending on whether _clientCipher is null or not:

var paddingMultiplier = _clientCipher is null ? (byte) 8 : Math.Max((byte) 8, _serverCipher.MinimumSize);

But I have not thought about it too hard.

@Rob-Hague
Copy link
Collaborator

@okarpov could you please try with the following patch? (save as diff.patch and run git apply diff.patch)

diff --git a/src/Renci.SshNet/Session.cs b/src/Renci.SshNet/Session.cs
index 257cf8c2..cef26c65 100644
--- a/src/Renci.SshNet/Session.cs
+++ b/src/Renci.SshNet/Session.cs
@@ -1039,7 +1039,11 @@ namespace Renci.SshNet
 
             DiagnosticAbstraction.Log(string.Format("[{0}] Sending message '{1}' to server: '{2}'.", ToHex(SessionId), message.GetType().Name, message));
 
-            var paddingMultiplier = _clientCipher is null ? (byte) 8 : Math.Max((byte) 8, _serverCipher.MinimumSize);
+            // Use locals to avoid races
+            var clientCipher = _clientCipher;
+            var clientMac = _clientMac;
+
+            var paddingMultiplier = clientCipher is null ? (byte) 8 : Math.Max((byte) 8, clientCipher.MinimumSize);
             var packetData = message.GetPacket(paddingMultiplier, _clientCompression);
 
             // take a write lock to ensure the outbound packet sequence number is incremented
@@ -1049,19 +1053,19 @@ namespace Renci.SshNet
                 byte[] hash = null;
                 var packetDataOffset = 4; // first four bytes are reserved for outbound packet sequence
 
-                if (_clientMac != null)
+                if (clientMac != null)
                 {
                     // write outbound packet sequence to start of packet data
                     Pack.UInt32ToBigEndian(_outboundPacketSequence, packetData);
 
                     // calculate packet hash
-                    hash = _clientMac.ComputeHash(packetData);
+                    hash = clientMac.ComputeHash(packetData);
                 }
 
                 // Encrypt packet data
-                if (_clientCipher != null)
+                if (clientCipher != null)
                 {
-                    packetData = _clientCipher.Encrypt(packetData, packetDataOffset, packetData.Length - packetDataOffset);
+                    packetData = clientCipher.Encrypt(packetData, packetDataOffset, packetData.Length - packetDataOffset);
                     packetDataOffset = 0;
                 }
 

@okarpov
Copy link
Author

okarpov commented Nov 17, 2023

@okarpov could you please try with the following patch? (save as diff.patch and run git apply diff.patch)

diff --git a/src/Renci.SshNet/Session.cs b/src/Renci.SshNet/Session.cs
index 257cf8c2..cef26c65 100644
--- a/src/Renci.SshNet/Session.cs
+++ b/src/Renci.SshNet/Session.cs
@@ -1039,7 +1039,11 @@ namespace Renci.SshNet
 
             DiagnosticAbstraction.Log(string.Format("[{0}] Sending message '{1}' to server: '{2}'.", ToHex(SessionId), message.GetType().Name, message));
 
-            var paddingMultiplier = _clientCipher is null ? (byte) 8 : Math.Max((byte) 8, _serverCipher.MinimumSize);
+            // Use locals to avoid races
+            var clientCipher = _clientCipher;
+            var clientMac = _clientMac;
+
+            var paddingMultiplier = clientCipher is null ? (byte) 8 : Math.Max((byte) 8, clientCipher.MinimumSize);
             var packetData = message.GetPacket(paddingMultiplier, _clientCompression);
 
             // take a write lock to ensure the outbound packet sequence number is incremented
@@ -1049,19 +1053,19 @@ namespace Renci.SshNet
                 byte[] hash = null;
                 var packetDataOffset = 4; // first four bytes are reserved for outbound packet sequence
 
-                if (_clientMac != null)
+                if (clientMac != null)
                 {
                     // write outbound packet sequence to start of packet data
                     Pack.UInt32ToBigEndian(_outboundPacketSequence, packetData);
 
                     // calculate packet hash
-                    hash = _clientMac.ComputeHash(packetData);
+                    hash = clientMac.ComputeHash(packetData);
                 }
 
                 // Encrypt packet data
-                if (_clientCipher != null)
+                if (clientCipher != null)
                 {
-                    packetData = _clientCipher.Encrypt(packetData, packetDataOffset, packetData.Length - packetDataOffset);
+                    packetData = clientCipher.Encrypt(packetData, packetDataOffset, packetData.Length - packetDataOffset);
                     packetDataOffset = 0;
                 }
 

still getting two exceptions


System.ArgumentException: data
   at Renci.SshNet.Security.Cryptography.BlockCipher.Encrypt(Byte[] data, Int32 offset, Int32 length) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\Security\Cryptography\BlockCipher.cs:line 105
   at Renci.SshNet.Session.SendMessage(Message message) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\Session.cs:line 1070
   at Renci.SshNet.PasswordAuthenticationMethod.Authenticate(Session session) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\PasswordAuthenticationMethod.cs:line 98
   at Renci.SshNet.AuthenticationMethod.Renci.SshNet.IAuthenticationMethod.Authenticate(ISession session) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\AuthenticationMethod.cs:line 60
   at Renci.SshNet.ClientAuthentication.TryAuthenticate(ISession session, AuthenticationState authenticationState, String[] allowedAuthenticationMethods, SshAuthenticationException& authenticationException) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\ClientAuthentication.cs:line 116
   at Renci.SshNet.ClientAuthentication.Authenticate(IConnectionInfoInternal connectionInfo, ISession session) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\ClientAuthentication.cs:line 66
   at Renci.SshNet.ConnectionInfo.Authenticate(ISession session, IServiceFactory serviceFactory) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\ConnectionInfo.cs:line 452
   at Renci.SshNet.Session.ConnectAsync(CancellationToken cancellationToken) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\Session.cs:line 763
   at Renci.SshNet.BaseClient.CreateAndConnectSessionAsync(CancellationToken cancellationToken) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\BaseClient.cs:line 545
   at Renci.SshNet.BaseClient.ConnectAsync(CancellationToken cancellationToken) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\BaseClient.cs:line 284





Renci.SshNet.Common.SshException: Message type 52 is not valid in the current context.
   at Renci.SshNet.Session.WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\Session.cs:line 989
   at Renci.SshNet.Session.Renci.SshNet.ISession.WaitOnHandle(WaitHandle waitHandle) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\Session.cs:line 839
   at Renci.SshNet.Channels.Channel.WaitOnHandle(WaitHandle waitHandle) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\Channels\Channel.cs:line 511
   at Renci.SshNet.Channels.ChannelSession.Open() in SSH.NET-rsa-sha2-256\src\Renci.SshNet\Channels\ChannelSession.cs:line 73
   at Renci.SshNet.SshCommand.BeginExecute(AsyncCallback callback, Object state) in SSH.NET-rsa-sha2-256\src\Renci.SshNet\SshCommand.cs:line 256
   at Renci.SshNet.SshCommand.BeginExecute() in SSH.NET-rsa-sha2-256\src\Renci.SshNet\SshCommand.cs:line 171

@okarpov
Copy link
Author

okarpov commented Nov 17, 2023

with nuget lbrary:

Renci.SshNet.Common.SshException: Message type 52 is not valid in the current context.
   at Renci.SshNet.SshMessageFactory.Create(Byte messageNumber)
   at Renci.SshNet.Session.ReceiveMessage(Socket socket)
   at Renci.SshNet.Session.MessageListener()
--- End of stack trace from previous location ---
   at Renci.SshNet.Session.WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout)
   at Renci.SshNet.Channels.ChannelSession.Open()
   at Renci.SshNet.SshCommand.BeginExecute(AsyncCallback callback, Object state)

@Rob-Hague
Copy link
Collaborator

Interesting. Message type 52 is SSH_MSG_USERAUTH_SUCCESS...

@okarpov
Copy link
Author

okarpov commented Nov 21, 2023

i think i have found the root of this issue.
make SFTP.ConnectAsync(CancellationToken.None) call without await and then make call to SFTP.Disconnect()

it looks like in this scenario it throws that different types of exceptions like Message type 52 and the "data"

@Rob-Hague
Copy link
Collaborator

Ah right, yes, I would expect something like that to result in strange/undefined behaviour. I don't think there would be anything worth changing in the library for this scenario.

@WojciechNagorski
Copy link
Collaborator

@okarpov Thanks for answering, so that someone may find your command in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants