SFTP Interactive Auth with Certificate

0 votes
asked Jun 4 by toby (160 points)

Hi,

I think I have a variation on this question:
https://forum.rebex.net/9225/sftp-error-password-keyboard-interactive

The server that I am trying to log in to requires both keyboard-interactive and certificate based authentication.

The error message I am receiving is:
Authentication was partially successful, but server requires additional authentication with: 'keyboard-interactive'.

Note that 'password' option is missing (see similar question).

I am using the login method suggested in that post. Note that I have also successfully tested 'standard authentication', certificate, and keyboard interactive on other servers. I know the code is setup correctly for these authentication types. ... but the combination seems to be a problem.

I can confirm that login works correctly with ZOC. I am using Rebex v5.0.7077.0.

Thanks in advance,

Toby

Applies to: Rebex SFTP

1 Answer

0 votes
answered Jun 4 by Lukas Matyska (58,290 points)

Hello, it seems that you called Sftp.Login("username", SshPrivateKey), please try to call Sftp.Login("username", "password", SshPrivateKey) overload instead.

If the server's "keyboard-interactive prompt" is recognized as "password prompt" the given password will be used automatically.

If the server's "keyboard-interactive prompt" is not recognized, you have to also register the Sftp.AuthenticationRequest event. For details, see https://www.rebex.net/sftp.net/features/authentication.aspx#keyboard-interactive

This should handle 99% of cases. If you cannot use Sftp.Login("username", "password", SshPrivateKey) for some reason, please let us know. We will suggest you different solution.

commented Jun 5 by toby (160 points)
Thanks for the quick reply Lukas.

I am already following the suggested approach.  I am calling the Login method suggested and I have registered the AuthenticationRequest event to prompt the user if needed.  This approach is working well for lots of different scenarios including keyboard interactive login and certificate based login - so I know it is basically correct.

Note that the server requires BOTH forms of authentication.  Certificate plus a dynamically generated code which not known before attempting login.  Therefore, the password is null.
commented Jun 8 by Lukas Matyska (58,290 points)
Please, try to set password to the empty string.
It has a little different meaning:
- null = don't use password at all.
- empty string = use empty password.

Since your server requests "dynamic code" using keyboard-interactive, the password value will not be used very probably (note: password can still be used in some cases, for example if the keyboard-interactive prompt contains phrase "password:").

If using empty password does not solve your problem. Please, use this approach:

    try
    {
        client.Login("username", SshPrivateKey);
    }
    catch (SftpException ex)
    {
        if (ex.Message.StartsWith("Authentication was partially successful"))
            client.Login("username");
        else
            throw;
    }
commented Jun 9 by toby (160 points)
Ok.  Thanks Lukas.

I will give these approaches a try and get back to you.

Is it possible to get a more elegant solution in the next release?  It is difficult a for user to input an 'empty string' password into a text box.  Also, checking a (localized?) exception message to indicate a different approach seems less than ideal.

I think these are great short term approaches, but I would prefer a more robust solution long term.

Thanks for your help!
commented Jun 9 by Lukas Matyska (58,290 points)
Yes, you are absolutely correct. Checking exception message is not a good idea.
We already have a ticket to add SshExceptionStatus.AuthenticationPartialSuccess - so, instead checking ex.Message you will be able to check ex.Status.
I will increase its priority

However, the exception message is thrown by our code - we are not going to change the message until SshExceptionStatus.AuthenticationPartialSuccess is introduced. So, checking ex.Message is safe solution for now (we don't use localized messages).

Note: To enter 'empty string' password into a text box is very easy - just leave the text box empty.
commented Jun 10 by toby (160 points)
Hi Lukas,

I just wanted to confirm that the solution with a 'empty' password is working.  Because a empty textbox already has the meaning of 'null' for other use cases, I have had to implement this in a really hacky way for the time being (a password of space is used to indicate the empty string IF a certificate is used).

Maybe I should always set the password to empty if it is null?  Would this break other use cases?  Looking forward to a more long-term solution.

Thanks for your help!

Toby
commented Jun 12 by Lukas Matyska (58,290 points)
It is up to you. You have to determine, whether empty text-box means "use no password" or "use empty password".

You can for example include a check-box on your form, which determines whether a password is used or not.

If I would do such an application, I would do this:
Try to use empty password, if the authentication fails, mask the error and use null password instead, which will lead to showing a prompt dialog (provided by the AuthenticationRequest event).
I think, this is the most user friendly solution. If the user does not fill a password, he will be prompted if it is required.
commented Jun 26 by toby (160 points)
Sorry for the slow reply.  There seems to be a problem with email notifications on this forum (at least, for me).

If I am logging in from a command line, how does the server differentiate between a null or empty password?  

It would be much better for this to be handled internally by Rebex.  Probably with a different login method that makes the intention clear.  I think:

Sftp.Login(Settings.Username, certificate);

Should correctly handle the situation where a password is not provided.

Sftp.Login(Settings.Username, password, certificate);

Should pass whatever password was provided to the server.

With the solution you suggested above, what happens if the user enters the wrong password on the first auth attempt?  Won't this be raised as a exception which then - immediately - leads to the user being re-prompted?  This may not be the intention of the client application.

Or, maybe a null password should just never be passed to the server?

Thanks for your help,

Toby
commented Jun 26 by toby (160 points)
Also, if no password is needed and authentication is handled with just a certificate, how will the server respond to an (unexpected) empty string password?

I suppose my confusion might be because if I tell the server my password is null - it will not prompt me to enter my password.  If I tell the server my password is <empty> - it will prompt me.  If anything, I would expect this to be the other way around?
commented Jun 26 by Lukas Matyska (58,290 points)
Please note that my last suggestion was intended ONLY for case when a user DOES NOT FILL a password. In such case it can mean two things:
1. "I don't want to use password" - it corresponds to null password.
2. "I have empty password" - it corresponds to empty string password.

So, I suggested to handle this by trying both variants.

Of course, if the user specifies a non-empty password, you will use that exact password. If it fails, you will report the error to the user immediately.

Also please note that everything works as expected:

1. Sftp.Login(Settings.Username, certificate) - does not send password to the server.
2. Sftp.Login(Settings.Username, password, certificate) - sends specified password to the server - ONLY if the password is null, no password is sent to the server.

Also please note that everything depends on enabled authentication methods on the server as well. For example,
- if the server authenticates successfully just with certificate, no password is sent to the server.
- if server allows 'password' authentication method - the provided password is sent to the server.
- if server allows 'keyboard-interactive' authentication method - the specified password value is used only if the prompt contains phrase "password:" - if it does not contains the phrase, the AuthenticationRequest event is raised to read the "user answer".
commented Jun 29 by toby (160 points)
I really appreciate the detailed reply Lukas - thanks!

I will implement the solution using the recommended approach.

Thanks again for your help with this issue.

Toby
...