Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Can't connect (SCP, SSH) in Xamarin Android #807

Closed
stealthrabbi opened this issue Apr 15, 2021 · 14 comments
Closed

Can't connect (SCP, SSH) in Xamarin Android #807

stealthrabbi opened this issue Apr 15, 2021 · 14 comments

Comments

@stealthrabbi
Copy link

Calling Connect() with an SSH or SCP client (and likely others) causes this exception. Does this library not work in Xamarin Android?

I don't see where in this library ti's throwing NotImplementedException, so I'm guessing something missing in Mono / .NET Standard?

2021-04-15 12:29:05.030 16384-16427/? E/MySessionStarter: Failed uploading file: System.NotImplementedException: The method or operation is not implemented.
      at Renci.SshNet.Session.WaitOnHandle (System.Threading.WaitHandle waitHandle, System.TimeSpan timeout) [0x00041] in <c7169cd606324a41b931acc40c516428>:0 
      at Renci.SshNet.Session.WaitOnHandle (System.Threading.WaitHandle waitHandle) [0x0000d] in <c7169cd606324a41b931acc40c516428>:0 
      at Renci.SshNet.Session.Connect () [0x0017b] in <c7169cd606324a41b931acc40c516428>:0 
      at Renci.SshNet.BaseClient.CreateAndConnectSession () [0x00053] in <c7169cd606324a41b931acc40c516428>:0 
      at Renci.SshNet.BaseClient.Connect () [0x0001f] in <c7169cd606324a41b931acc40c516428>:0 
    ....
    ```
@drwtsn32x
Copy link

Did you solve this yet? What version of mono are you using?

@stealthrabbi
Copy link
Author

Not solved. I don't know what version of Mono I'm using. I believe it was roughly the latest Xamarin.

@drwtsn32x
Copy link

When you get a chance, if you could check the mono version that'd be great....

$ mono --version

I'm exploring possibly the same issue with a different product that uses the SSH.NET library. Wondering if the mono version is the culprit.

@stealthrabbi
Copy link
Author

I don't explicitly have mono installed -- that's not needed for Xamarin work. The Mono.Android assembly that VS is using for the Xamarin Android project is in a folder named C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\ReferenceAssemblies\Microsoft\Framework\MonoAndroid\v9.0, but the actual DLL has a Product version of 11.0.2.0;

@drwtsn32x
Copy link

Ok, on the other project I'm working on we discovered that mono doesn't support ECDSA keys. SSH.NET library will throw the NotImplemented exception when it's running via mono. (It works fine when using native .NET on Windows though.)

So you might be able to "solve" your problem by not using an ECDSA key...

@stealthrabbi
Copy link
Author

What you say about the keys may be right, but I think my issue is happening way before a connection. It's related to Session.WaitOnHandle being not implemented.

@ts678
Copy link

ts678 commented May 12, 2021

It's related to Session.WaitOnHandle being not implemented.

It seems Session.WaitOnHandle is in https://github.com/sshnet/SSH.NET/blob/develop/src/Renci.SshNet/Session.cs
You can see comments there about the receive thread. I'm not an SSH.NET developer. It'd be nice if they can help.

It might be waiting at the below for the receive thread to either receive, or find an exception, and it got exception:

internal void WaitOnHandle(WaitHandle waitHandle, TimeSpan timeout)

I think my issue is happening way before a connection

The stack trace names suggest that it's working on connect, but it likely died before SSH connection was finished.
The behavior we see with certain SFTP servers such as Bitvise (but not OpenSSH, at least so far) is a failure after a

Server: Elliptic Curve Diffie-Hellman Key Exchange Reply, New Keys
Message Code: Elliptic Curve Diffie-Hellman Key Exchange Reply (31)
is received, containing
KEX host key (type: ecdsa-sha2-nistp384)
I think the received protocol is RFC 5656 ECDH Key Exchange here.

Processing of that server SSH_MSG_KEX_ECDH_REPLY might be here:

/// <summary>
/// Called when <see cref="NewKeysMessage"/> message received.
/// </summary>
/// <param name="message"><see cref="NewKeysMessage"/> message.</param>
internal void OnNewKeysReceived(NewKeysMessage message)

and at some point the key from the server might hit here:

/// <summary>
/// Initializes a new instance of the <see cref="EcdsaKey"/> class.
/// </summary>
/// <param name="data">DER encoded private key data.</param>
public EcdsaKey(byte[] data)

ECDsa Class and ECDsaCng Class get involved, and so maybe it hits the NotImplementedException around here.

NotImplementedException has been in ECDsaCng.cs a long time, maybe added here, then later exposed through
Support newer SSH Ciphers and MACs #53. If you're still on the 2016 release, ignore all this. It applies to 2020's.

Any SSH.NET developer comments? Could these very welcome new capabilities be exposing an old gap in mono?
Please forgive any mistakes in the details. I don't have a debugger, or know the protocol or the code all that well.

@ts678
Copy link

ts678 commented May 12, 2021

I'm noticing the 2017 mono change did a similar NotImplementedException to RsaCng.cs just below ECDsaCng.cs

@drwtsn32x
Copy link

(but not OpenSSH, at least so far)

I was able to reproduce with an OpenSSH server by using an ECDSA key.

@Joannick
Copy link

Hi friend,
so did you found a solution about this? I've seen an other solution is Rebex SFTP Nugget but licence is 350$.
Thanks

@stealthrabbi
Copy link
Author

My solution was in Xamarin, to create a binding to the JSCH java library and use that in my xamarin android proj.

@ts678
Copy link

ts678 commented May 22, 2021

A workaround is try new ECDsaCng() to see if it's implemented. If exception occurs, go through HostKeyAlgorithms.Keys, and HostKeyAlgorithms.Remove(key) the ones beginning with ecdsa (inspired by Limit what algorithms or ciphers are used #730).

likeMyCoffee added a commit to likeMyCoffee/SSH.NET that referenced this issue Jun 29, 2021
Certain Cisco devices do not adhere to RFC4342 and do not reply if the client identifies first.
Since identifcation can be in random order it will give random connection issues because the SSH_MSG_KEXINIT will not be sent if the client is faster.

Since SSH.Net is not at fault and compatibility with Cisco (and possibly other) devices is something that can easily be supported I've written this modification.

Added LazyIdentification to the ConnectionInfo object to allow late identification in ProtocolVersionExchange.
Overloaded 'Start' function to keep the original functionality and tests intact.

Highly likely fixes issues sshnet#752, sshnet#778, sshnet#469 and might help with sshnet#798, sshnet#767, sshnet#807
likeMyCoffee added a commit to likeMyCoffee/SSH.NET that referenced this issue Jun 29, 2021
Certain Cisco devices do not adhere to RFC4342 and do not reply if the client identifies first.
Since identifcation can be in random order it will give random connection issues because the SSH_MSG_KEXINIT will not be sent if the client is faster.

Since SSH.Net is not at fault and compatibility with Cisco (and possibly other) devices is something that can easily be supported I've written this modification.

Added LazyIdentification to the ConnectionInfo object to allow late identification in ProtocolVersionExchange.
Overloaded 'Start' function to keep the original functionality and tests intact.

Highly likely fixes issues sshnet#752, sshnet#778, sshnet#469 and might help with sshnet#798, sshnet#767, sshnet#807
@TechnoFairyGirl
Copy link

TechnoFairyGirl commented Sep 1, 2021

ECDSA is simply not implemented on Mono. The only real fix would be to use a different implementation, such as the one provided by Bouncy Castle.

You can work around the issue by removing the ECDSA algorithms from connectionInfo.HostKeyAlgorithms if System.Security.Cryptography.ECDsaCng is unavailable.

try { using (var ecdsa = new System.Security.Cryptography.ECDsaCng()) ; }
catch (NotImplementedException)
{
    var algsToRemove = connectionInfo.HostKeyAlgorithms.Keys.Where(algName => algName.StartsWith("ecdsa")).ToArray();
    foreach (var algName in algsToRemove) connectionInfo.HostKeyAlgorithms.Remove(algName);
}

If you get Renci.SshNet.Common.SshConnectionException: 'An established connection was aborted by the server.' on connect after adding the code above, then the server doesn't have any mutually agreeable host key algorithms now that you've removed the ECDSA ones. This can be solved on the server by adding ssh-rsa to HostKeyAlgorithms in sshd_config (or the equivalent for whatever SSH server you have).

@Rob-Hague
Copy link
Collaborator

Should be fixed by #1461

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

6 participants