0 votes
by (330 points)
edited

I'm writing an SFTP app which loops through a list of sites, logs in, and does its thing. Some of the sites require a password, and some require a password and a key. Since the list doesn't track which is which, I'm doing:

try
{
    sftp.Login(username, password);
}
catch (SftpException)
{
    sftp.Login(username, password, key);
}

But the second call to Login() throws a NullReferenceException, even though sftp, username, and key are all non-null. Any suggestions here?

What I would really like to be able to do is just call Login() once, with the username, password, and key. But Sftp presents the key to the server first, and if the server doesn't recognize the key (i.e., it only wants the password), Sftp throws an exception. It would be nice if Sftp would instead proceed to try password authentication if the password is non-null and only throw an exception if that doesn't work.

Applies to: Rebex SFTP

3 Answers

0 votes
by (330 points)
edited

I see the immediate problem: I need another sftp.Connect() before the second Login(). An Sftp.Reconnect() method would be useful here to avoid repeating the hostname. A more useful exception would also be nice.

I also wish there were a more compact solution to this situation, when you want to throw a password and a key at the server and just let the component work it out.

0 votes
by (144k points)
edited

I'm looking into this issue and so far, I have not been able to reproduce it. I tried the following code:

        string username = "test01";
        string password = null;
        SshPrivateKey key = SshPrivateKey.Generate();

        try
        {
            sftp.Login(username, password);
        }
        catch (SftpException)
        {
            sftp.Login(username, password, key);
        }

But instead of a NullReferenceException thrown by the second Login() call, an ArgumentNullException is thrown by the first Login() call.


"It would be nice if Sftp would instead proceed to try password authentication if the password is non-null and only throw an exception if that doesn't work."

I understand that this would be useful for your scenario, but it might not be a good idea generally. In most use cases, if a private key is rejected by the server, it means that something is wrong - and still trying the password despite one failure would only waste resources and complicate debugging.

However, we can add an option that would instruct the Login(userName, password, privateKey) method to try password authentication first. This way, if it succeeded, no private key authentication would occur and it would not matter whether the key is correct or not. This should work for you as well. What do you think?

0 votes
by (330 points)
edited

I wasn't clear about my initial problem. All of the sites I currently connect to have passwords; some use a key in addition. So in your test code, password would have a value, not null. For the sites which also need the key, the first Login(username, password) fails with an SftpException, and then I need to retry with Login(username, password, key). If I don't do another Sftp.Connect() before the second Login(), I get the null reference exception.

(I know the real solution on my end is to track more specifically which sites need which auth and make the appropriate calls. I'm dealing with a rewrite of a legacy system which doesn't have this info; the Delphi components we used previously handled all of this transparently as I describe.)


However, we can add an option that would instruct the Login(userName, password, privateKey) method to try password authentication first.

Would that correctly handle the case of a server which requires password and key? Or do those servers expect the key first, as Login(username, password, key) currently does?

Thanks.

by (144k points)
edited

Thanks for clarifying the problem, we have been able to reproduce the NullReferenceException and it is actually caused by a bug in Rebex SFTP. We will fix it and mail you a new version to try. Thanks for reporting this!

by (144k points)
edited

The servers that require both the password and key don't impose any particular order, so this should work. We will include this with the fix for the NullReferenceException as well.

by (13.0k points)
edited

UPDATE: The fix is part of Release 2012 R1 - http://blog.rebex.net/news/archive/2012/03/08/version-2012-r1.aspx . It's now possible to call Sftp.Login again if it fails.

by (144k points)
edited

UPDATE: The option to try password authentication first is also a part of Release 2012 R1. Set the following value to try to enable it:

sftp.Settings.TryPasswordFirst = true; // where 'sftp' is an instance of Sftp
...