TryAuthenticate gets stuck in an infinite recursive loop if the authentication passes partially but requires a 2nd part. This happens whether a single or multiple authentication methods are provided as part of the ConnectionInfo constructor.
TryAuthenticate calls itself to pass the next authentication method to the server, but the list of authentication methods it passes in doesn't exclude the authentication methods already completed. As such, the same authentication method is tried over and over again without ever moving to the next authentication method.
Taking a specific example, suppose that password and privateKey methods are used. Password passes the initial Authenticate call and the result is PartialSuccess. TryAuthenticate is called, and the new list of authenticated methods is still { password, privateKey }. Password is verified again with a result of PartialSuccess. This continues until stack overflow.
Duped with ServU SFTP Server and SSH.NET Changeset 35920
__Recommended solution__: Filter the passed authentication methods down exclude those which have already passed. This needs to be done by authentication method type to ensure that, for example, for a given password authentication returning partial success that we do not attempt any other password authentications but we do attempt all non-failed private keys.
If we want to be able to try different username/auth method combinations then we'd also have to track the difference between failedAuthenticationMethods at the top level and failedAuthenticationMethods found during a PartialSuccess state since I believe it may be possible to fail authentication during PartialSuccess state but succeed from the root level. Not sure how SFTP or SSH.NET responds to switching user names after a PartialSuccess though. Maybe multiple usernames with a single ConnectionInfo is just a weird case that we don't need/want to support.
I've attached a suggested change for the basic fix based on ConnectionInfo.cs Changeset 35920
Comments: ** Comment from web user: drieseng **
TryAuthenticate calls itself to pass the next authentication method to the server, but the list of authentication methods it passes in doesn't exclude the authentication methods already completed. As such, the same authentication method is tried over and over again without ever moving to the next authentication method.
Taking a specific example, suppose that password and privateKey methods are used. Password passes the initial Authenticate call and the result is PartialSuccess. TryAuthenticate is called, and the new list of authenticated methods is still { password, privateKey }. Password is verified again with a result of PartialSuccess. This continues until stack overflow.
Duped with ServU SFTP Server and SSH.NET Changeset 35920
__Recommended solution__: Filter the passed authentication methods down exclude those which have already passed. This needs to be done by authentication method type to ensure that, for example, for a given password authentication returning partial success that we do not attempt any other password authentications but we do attempt all non-failed private keys.
If we want to be able to try different username/auth method combinations then we'd also have to track the difference between failedAuthenticationMethods at the top level and failedAuthenticationMethods found during a PartialSuccess state since I believe it may be possible to fail authentication during PartialSuccess state but succeed from the root level. Not sure how SFTP or SSH.NET responds to switching user names after a PartialSuccess though. Maybe multiple usernames with a single ConnectionInfo is just a weird case that we don't need/want to support.
I've attached a suggested change for the basic fix based on ConnectionInfo.cs Changeset 35920
Comments: ** Comment from web user: drieseng **
If I understand you correctly, then the scenario is something like this:
1. list of allowed authentications is password, privatekey
2. authentication is partially successful using password authentication
3. list of allowed authentications is password, privatekey
4. authentication is partially successful using password authentication
...
I don't understand why - after step 2 - the list of allowed authentications is still "password, privatekey".
For OpenSSH, the list of allowed authentications after step 2 woud definitely be "privatekey".