FileServer: mixed authentication methods possible?

+1 vote
asked Jul 28, 2016 by oki (250 points)

how can I mix authenticationmethods in FileServer componenent for users? and how can I change the order of Authentication methods?

here is the Authentication codesnipped:

private static void Sshd_Authentication(object sender, AuthenticationEventArgs e)
{
    // make sure the user exists
    FileServerUser user = sshd.Users[e.UserName];
    if (user != null)
    {
        // if it's a 'public key' user, check the key
        var userWithKey = user as SshUsers;
        if (userWithKey != null && userWithKey.Key.Equals(e.Key)) // userWithKey.key is populated correct but: e.Key is empty!
        {
            e.Accept(userWithKey);
            return;
        }
        // otherwise, check the password
        if (user.CheckPassword(e.Password))
        {
            e.Accept(user);
            return;
        }
    }
}

here is my FileServer instantiating:

const string sshdPpkFilename = "sshd.ppk";
const string sshdPpkPass = "pass";
const string sshdRootPath = "root";
sshd = new FileServer();
sshd.LogWriter = new ConsoleLogWriter(LogLevel.Debug);

sshd.Bind(FileServerProtocol.Tunneling);
sshd.Bind(FileServerProtocol.Shell);
sshd.Bind(FileServerProtocol.Sftp);
sshd.Settings.UseNativeFilesystem = false;
sshd.Settings.ShellEncoding = Encoding.UTF8;
sshd.Settings.MaxAuthenticationAttempts = 3;
sshd.Settings.SshParameters.EncryptionAlgorithms = SshEncryptionAlgorithm.AES;
sshd.Settings.SshParameters.AuthenticationMethods = SshAuthenticationMethod.Any;
sshd.Settings.SshParameters.Compression = true;
sshd.Settings.SshParameters.KeyExchangeAlgorithms = SshKeyExchangeAlgorithm.DiffieHellmanGroupExchangeSHA256 | SshKeyExchangeAlgorithm.DiffieHellmanGroupExchangeSHA1;

sshd.Keys.Add(new SshPrivateKey(sshdPpkFilename, sshdPpkPass));

// user with name/password:
sshd.Users.Add("admin", "gg", Path.GetFullPath(sshdRootPath), ShellType.Default);
// http://www.rebex.net/file-server/features/authentication.aspx - User with Public Key Auth.
sshd.Users.Add(new SshUsers("o", new SshPublicKey(Path.GetFullPath(@"test.pub")), Path.GetFullPath(sshdRootPath), ShellType.Default));

sshd.Authentication += Sshd_Authentication;
sshd.Start();

the user "admin" authenticates with password.
User "o" should authenticate by public key (Key is loaded, Fingerprint verified within Visual Studio Debugger), but the password prompt appear.
he last lines from log when user "o" is prompted for Password:

2016-07-28 18:20:04.993 DEBUG FileServer(1)[12] SSH: Session 1: Current encryptor is aes256-ctr/hmac-sha2-256.
2016-07-28 18:20:05.111 DEBUG FileServer(1)[12] SSH: Session 1: Current decryptor is aes256-ctr/hmac-sha2-256.
2016-07-28 18:20:05.112 DEBUG FileServer(1)[12] SSH: Session 1: Key exchange finished.
2016-07-28 18:20:05.113 DEBUG FileServer(1)[11] SSH: Session 1: Performing authentication.
2016-07-28 18:20:09.183 DEBUG FileServer(1)[11] SSH: Session 1: Starting authentication as 'o' for 'ssh-connection'.

1 Answer

0 votes
answered Jul 29, 2016 by Lukas Pokorny (86,990 points)

You can use PreAuthentication event to specify authentication methods allowed for each user. The event handler might look like this:

private static void Sshd_PreAuthentication(object sender, PreAuthenticationEventArgs e)
{
    // make sure the user exists
    FileServerUser user = sshd.Users[e.UserName];
    if (user != null)
    {
        // if it's a 'public key' user, ask for public key authentication
        var userWithKey = user as SshUsers;
        if (userWithKey != null && userWithKey.Key.Equals(e.Key)) // userWithKey.key is populated correct but: e.Key is empty!
        {
            // only allow public key authentication for key-only users
            e.Accept(AuthenticationMethods.PublicKey);
            return;
        }
    }

    // otherwise, ask for password authentication
    // (if the user doesn't exist, pretend it does)
    e.Accept(AuthenticationMethods.Password);
}

It's currently not possible to change the order of authentication methods. However, this would be of limited use because the list of supported authentication methods is not supposed to be sorted by preference.

commented Jul 29, 2016 by oki (250 points)
Thank you for your quick reply Lukas,
tish sounds good. Copied the snippet in my code, fixed the one row to:
 if (userWithKey != null && userWithKey.Key != null)
compiled and tested: e.Accept(AuthenticationMethods.PublicKey); will call for User with a public key.

but: in "public class PreAuthenticationEventArgs" the "_allowedMethods" is initialized with "Password". With:" _acceptedMethods = _allowedMethods & methods; a "Password" & "PublicKey" results a "No supported authentication methods available (server Sent)" message.
commented Jul 29, 2016 by Lukas Pokorny (86,990 points)
edited Jul 29, 2016 by Lukas Pokorny
Sorry! I forgot to mention that you also need to set this:
sshd.Settings.AllowedAuthenticationMethods = AuthenticationMethods.Any;

(See http://www.rebex.net/file-server/features/authentication.aspx#advanced-provider for a working example.)
commented Jul 29, 2016 by oki (250 points)
whow, got it. Where is the difference between?
sshd.Settings.SshParameters.AuthenticationMethods = SshAuthenticationMethod.Any;

sshd.Settings.AllowedAuthenticationMethods = AuthenticationMethods.Any;
commented Jul 29, 2016 by Lukas Pokorny (86,990 points)
In future, when we add support for additional non-SSH protocols such as FTP/SSL Settings.AllowedAuthenticationMethods will be shared by both SFTP/SSH and FTP/SSL, while Settings.SshParameters.AuthenticationMethods will only affect SSH.

At the moment, you don't usually need to set Settings.SshParameters.AuthenticationMethods, although it can still be used to specify whether to ask for the password using "password" or "keyboard-interactive" authentication (or allow both).
...