| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- using Renci.SshNet.Common;
- using Renci.SshNet.IntegrationTests.Common;
- namespace Renci.SshNet.IntegrationTests
- {
- [TestClass]
- public class AuthenticationTests : IntegrationTestBase
- {
- private AuthenticationMethodFactory _authenticationMethodFactory;
- private IConnectionInfoFactory _connectionInfoFactory;
- private IConnectionInfoFactory _adminConnectionInfoFactory;
- private RemoteSshdConfig _remoteSshdConfig;
- [TestInitialize]
- public void SetUp()
- {
- _authenticationMethodFactory = new AuthenticationMethodFactory();
- _connectionInfoFactory = new LinuxVMConnectionFactory(SshServerHostName, SshServerPort, _authenticationMethodFactory);
- _adminConnectionInfoFactory = new LinuxAdminConnectionFactory(SshServerHostName, SshServerPort);
- _remoteSshdConfig = new RemoteSshd(_adminConnectionInfoFactory).OpenConfig();
- }
- [TestCleanup]
- public void TearDown()
- {
- _remoteSshdConfig?.Reset();
- using (var client = new SshClient(_adminConnectionInfoFactory.Create()))
- {
- client.Connect();
- // Reset the password back to the "regular" password.
- using (var cmd = client.RunCommand($"echo \"{Users.Regular.Password}\n{Users.Regular.Password}\" | sudo passwd " + Users.Regular.UserName))
- {
- Assert.AreEqual(0, cmd.ExitStatus, cmd.Error);
- }
- // Remove password expiration
- using (var cmd = client.RunCommand($"sudo chage --expiredate -1 " + Users.Regular.UserName))
- {
- Assert.AreEqual(0, cmd.ExitStatus, cmd.Error);
- }
- }
- }
- [TestMethod]
- public void Multifactor_PublicKey()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "publickey")
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- }
- [TestMethod]
- [TestCategory("Authentication")]
- public void Multifactor_PublicKey_Connect_Then_Reconnect()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "publickey")
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- client.Disconnect();
- client.Connect();
- client.Disconnect();
- }
- }
- [TestMethod]
- public void Multifactor_PublicKeyWithPassPhrase()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "publickey")
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPrivateKeyWithPassPhraseAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- }
- [TestMethod]
- [ExpectedException(typeof(SshPassPhraseNullOrEmptyException))]
- public void Multifactor_PublicKeyWithEmptyPassPhrase()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "publickey")
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPrivateKeyWithEmptyPassPhraseAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- }
- [TestMethod]
- public void Multifactor_PublicKey_MultiplePrivateKey()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "publickey")
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserMultiplePrivateKeyAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- }
- [TestMethod]
- public void Multifactor_PublicKey_MultipleAuthenticationMethod()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "publickey")
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethod(),
- _authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- }
- [TestMethod]
- public void Multifactor_KeyboardInteractiveAndPublicKey()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "keyboard-interactive,publickey")
- .WithChallengeResponseAuthentication(true)
- .WithKeyboardInteractiveAuthentication(true)
- .WithUsePAM(true)
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethodWithBadPassword(),
- _authenticationMethodFactory.CreateRegularUserKeyboardInteractiveAuthenticationMethod(),
- _authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- }
- [TestMethod]
- public void Multifactor_Password_ExceedsPartialSuccessLimit()
- {
- // configure server to require more successfull authentications from a given method than our partial
- // success limit (5) allows
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "password,password,password,password,password,password")
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- try
- {
- client.Connect();
- Assert.Fail();
- }
- catch (SshAuthenticationException ex)
- {
- Assert.IsNull(ex.InnerException);
- Assert.AreEqual("Reached authentication attempt limit for method (password).", ex.Message);
- }
- }
- }
- [TestMethod]
- public void Multifactor_Password_MatchPartialSuccessLimit()
- {
- // configure server to require a number of successfull authentications from a given method that exactly
- // matches our partial success limit (5)
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "password,password,password,password,password")
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- }
- [TestMethod]
- public void Multifactor_Password_Or_PublicKeyAndKeyboardInteractive()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "password publickey,keyboard-interactive")
- .WithChallengeResponseAuthentication(true)
- .WithKeyboardInteractiveAuthentication(true)
- .WithUsePAM(true)
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethod(),
- _authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- }
- [TestMethod]
- public void Multifactor_Password_Or_PublicKeyAndPassword_BadPassword()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "password publickey,password")
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethodWithBadPassword(),
- _authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- try
- {
- client.Connect();
- Assert.Fail();
- }
- catch (SshAuthenticationException ex)
- {
- Assert.IsNull(ex.InnerException);
- Assert.AreEqual("Permission denied (password).", ex.Message);
- }
- }
- }
- [TestMethod]
- public void Multifactor_PasswordAndPublicKey_Or_PasswordAndPassword()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "password,publickey password,password")
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod(),
- _authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethodWithBadKey());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethodWithBadPassword(),
- _authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- try
- {
- client.Connect();
- Assert.Fail();
- }
- catch (SshAuthenticationException ex)
- {
- Assert.IsNull(ex.InnerException);
- Assert.AreEqual("Permission denied (password).", ex.Message);
- }
- }
- }
- [TestMethod]
- public void Multifactor_PasswordAndPassword_Or_PublicKey()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "password,password publickey")
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod(),
- _authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethodWithBadKey());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- }
- [TestMethod]
- public void Multifactor_Password_Or_Password()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "password password")
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod(),
- _authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethodWithBadKey());
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- }
- }
- [TestMethod]
- public void KeyboardInteractive_PasswordExpired()
- {
- var temporaryPassword = new Random().Next().ToString();
- using (var client = new SshClient(_adminConnectionInfoFactory.Create()))
- {
- client.Connect();
- // Temporarity modify password so that when we expire this password, we change reset the password back to
- // the "regular" password.
- using (var cmd = client.RunCommand($"echo \"{temporaryPassword}\n{temporaryPassword}\" | sudo passwd " + Users.Regular.UserName))
- {
- Assert.AreEqual(0, cmd.ExitStatus, cmd.Error);
- }
- // Force the password to expire immediately
- using (var cmd = client.RunCommand($"sudo chage -d 0 " + Users.Regular.UserName))
- {
- Assert.AreEqual(0, cmd.ExitStatus, cmd.Error);
- }
- }
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "keyboard-interactive")
- .WithChallengeResponseAuthentication(true)
- .WithKeyboardInteractiveAuthentication(true)
- .WithUsePAM(true)
- .Update()
- .Restart();
- var keyboardInteractive = new KeyboardInteractiveAuthenticationMethod(Users.Regular.UserName);
- int authenticationPromptCount = 0;
- keyboardInteractive.AuthenticationPrompt += (sender, args) =>
- {
- Console.WriteLine(args.Instruction);
- foreach (var authenticationPrompt in args.Prompts)
- {
- Console.WriteLine(authenticationPrompt.Request);
- switch (authenticationPromptCount)
- {
- case 0:
- // Regular password prompt
- authenticationPrompt.Response = temporaryPassword;
- break;
- case 1:
- // Password expired, provide current password
- authenticationPrompt.Response = temporaryPassword;
- break;
- case 2:
- // Password expired, provide new password
- authenticationPrompt.Response = Users.Regular.Password;
- break;
- case 3:
- // Password expired, retype new password
- authenticationPrompt.Response = Users.Regular.Password;
- break;
- }
- authenticationPromptCount++;
- }
- };
- var connectionInfo = _connectionInfoFactory.Create(keyboardInteractive);
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- Assert.AreEqual(4, authenticationPromptCount);
- }
- }
- [TestMethod]
- public void KeyboardInteractiveConnectionInfo()
- {
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "keyboard-interactive")
- .WithChallengeResponseAuthentication(true)
- .WithKeyboardInteractiveAuthentication(true)
- .WithUsePAM(true)
- .Update()
- .Restart();
- var host = SshServerHostName;
- var port = SshServerPort;
- var username = User.UserName;
- var password = User.Password;
- #region Example KeyboardInteractiveConnectionInfo AuthenticationPrompt
- var connectionInfo = new KeyboardInteractiveConnectionInfo(host, port, username);
- connectionInfo.AuthenticationPrompt += delegate (object sender, AuthenticationPromptEventArgs e)
- {
- Console.WriteLine(e.Instruction);
- foreach (var prompt in e.Prompts)
- {
- Console.WriteLine(prompt.Request);
- prompt.Response = password;
- }
- };
- using (var client = new SftpClient(connectionInfo))
- {
- client.Connect();
- // Do something here
- client.Disconnect();
- }
- #endregion
- Assert.AreEqual(connectionInfo.Host, SshServerHostName);
- Assert.AreEqual(connectionInfo.Username, User.UserName);
- }
- [TestMethod]
- public void KeyboardInteractive_NoResponseSet_ThrowsSshAuthenticationException()
- {
- // ...instead of a cryptic ArgumentNullException
- // https://github.com/sshnet/SSH.NET/issues/382
- _remoteSshdConfig.WithAuthenticationMethods(Users.Regular.UserName, "keyboard-interactive")
- .WithChallengeResponseAuthentication(true)
- .WithKeyboardInteractiveAuthentication(true)
- .WithUsePAM(true)
- .Update()
- .Restart();
- var connectionInfo = _connectionInfoFactory.Create(new KeyboardInteractiveAuthenticationMethod(Users.Regular.UserName));
- using (var client = new SftpClient(connectionInfo))
- {
- try
- {
- client.Connect();
- Assert.Fail();
- }
- catch (SshAuthenticationException ex)
- {
- Assert.IsNull(ex.InnerException);
- Assert.IsTrue(ex.Message.StartsWith("AuthenticationPrompt.Response is null for prompt \"Password: \""), $"Message was \"{ex.Message}\"");
- }
- }
- }
- }
- }
|