2
0

ClientAuthenticationTest_Success_MultiList_PartialSuccessLimitReachedFollowedByFailureInAlternateBranch2.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using System.Collections.Generic;
  2. using Microsoft.VisualStudio.TestTools.UnitTesting;
  3. using Moq;
  4. using Renci.SshNet.Common;
  5. namespace Renci.SshNet.Tests.Classes
  6. {
  7. /// <summary>
  8. /// * ConnectionInfo provides the following authentication methods (in order):
  9. /// o password
  10. /// o publickey
  11. /// o keyboard-interactive
  12. /// * Partial success limit is 2
  13. ///
  14. /// none
  15. /// (1=FAIL)
  16. /// |
  17. /// +-------------------+
  18. /// | |
  19. /// publickey keyboard-interactive
  20. /// (2=PS) ^ (6=PS)
  21. /// | | |
  22. /// password | +-----------+
  23. /// (3=PS) | | |
  24. /// | | password publickey
  25. /// password | (7=SKIP) (8=FAIL)
  26. /// (4=PS) |
  27. /// | |
  28. /// password |
  29. /// (5=SKIP) |
  30. /// +------------+
  31. /// </summary>
  32. [TestClass]
  33. public class ClientAuthenticationTest_Success_MultiList_PartialSuccessLimitReachedFollowedByFailureInAlternateBranch2 : ClientAuthenticationTestBase
  34. {
  35. private int _partialSuccessLimit;
  36. private ClientAuthentication _clientAuthentication;
  37. private SshAuthenticationException _actualException;
  38. protected override void SetupData()
  39. {
  40. _partialSuccessLimit = 2;
  41. }
  42. protected override void SetupMocks()
  43. {
  44. var seq = new MockSequence();
  45. SessionMock.InSequence(seq).Setup(p => p.RegisterMessage("SSH_MSG_USERAUTH_FAILURE"));
  46. SessionMock.InSequence(seq).Setup(p => p.RegisterMessage("SSH_MSG_USERAUTH_SUCCESS"));
  47. SessionMock.InSequence(seq).Setup(p => p.RegisterMessage("SSH_MSG_USERAUTH_BANNER"));
  48. ConnectionInfoMock.InSequence(seq).Setup(p => p.CreateNoneAuthenticationMethod())
  49. .Returns(NoneAuthenticationMethodMock.Object);
  50. /* 1 */
  51. NoneAuthenticationMethodMock.InSequence(seq).Setup(p => p.Authenticate(SessionMock.Object))
  52. .Returns(AuthenticationResult.Failure);
  53. ConnectionInfoMock.InSequence(seq)
  54. .Setup(p => p.AuthenticationMethods)
  55. .Returns(new List<IAuthenticationMethod>
  56. {
  57. PasswordAuthenticationMethodMock.Object,
  58. PublicKeyAuthenticationMethodMock.Object,
  59. KeyboardInteractiveAuthenticationMethodMock.Object,
  60. });
  61. NoneAuthenticationMethodMock.InSequence(seq)
  62. .Setup(p => p.AllowedAuthentications)
  63. .Returns(new[] { "publickey", "keyboard-interactive" });
  64. /* Enumerate supported authentication methods */
  65. PasswordAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("password");
  66. PublicKeyAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("publickey");
  67. KeyboardInteractiveAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("keyboard-interactive");
  68. /* 2 */
  69. PublicKeyAuthenticationMethodMock.InSequence(seq)
  70. .Setup(p => p.Authenticate(SessionMock.Object))
  71. .Returns(AuthenticationResult.PartialSuccess);
  72. PublicKeyAuthenticationMethodMock.InSequence(seq)
  73. .Setup(p => p.AllowedAuthentications)
  74. .Returns(new[] { "password" });
  75. /* Enumerate supported authentication methods */
  76. PasswordAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("password");
  77. PublicKeyAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("publickey");
  78. KeyboardInteractiveAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("keyboard-interactive");
  79. /* 3 */
  80. PasswordAuthenticationMethodMock.InSequence(seq)
  81. .Setup(p => p.Authenticate(SessionMock.Object))
  82. .Returns(AuthenticationResult.PartialSuccess);
  83. PasswordAuthenticationMethodMock.InSequence(seq)
  84. .Setup(p => p.AllowedAuthentications)
  85. .Returns(new[] { "password" });
  86. /* Enumerate supported authentication methods */
  87. PasswordAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("password");
  88. PublicKeyAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("publickey");
  89. KeyboardInteractiveAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("keyboard-interactive");
  90. /* 4 */
  91. PasswordAuthenticationMethodMock.InSequence(seq)
  92. .Setup(p => p.Authenticate(SessionMock.Object))
  93. .Returns(AuthenticationResult.PartialSuccess);
  94. PasswordAuthenticationMethodMock.InSequence(seq)
  95. .Setup(p => p.AllowedAuthentications)
  96. .Returns(new[] { "password" });
  97. /* Enumerate supported authentication methods */
  98. PasswordAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("password");
  99. PublicKeyAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("publickey");
  100. KeyboardInteractiveAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("keyboard-interactive");
  101. /* 5: Record partial success limit reached exception, and skip password authentication method */
  102. PasswordAuthenticationMethodMock.InSequence(seq)
  103. .Setup(p => p.Name)
  104. .Returns("password-partial1");
  105. /* 6 */
  106. KeyboardInteractiveAuthenticationMethodMock.InSequence(seq)
  107. .Setup(p => p.Authenticate(SessionMock.Object))
  108. .Returns(AuthenticationResult.PartialSuccess);
  109. KeyboardInteractiveAuthenticationMethodMock.InSequence(seq)
  110. .Setup(p => p.AllowedAuthentications)
  111. .Returns(new[] { "password", "publickey" });
  112. /* Enumerate supported authentication methods */
  113. PasswordAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("password");
  114. PublicKeyAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("publickey");
  115. KeyboardInteractiveAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("keyboard-interactive");
  116. /* 7: Record partial success limit reached exception, and skip password authentication method */
  117. PasswordAuthenticationMethodMock.InSequence(seq)
  118. .Setup(p => p.Name)
  119. .Returns("password-partial2");
  120. /* 8 */
  121. PublicKeyAuthenticationMethodMock.InSequence(seq)
  122. .Setup(p => p.Authenticate(SessionMock.Object))
  123. .Returns(AuthenticationResult.Failure);
  124. PublicKeyAuthenticationMethodMock.InSequence(seq).Setup(p => p.Name).Returns("publickey");
  125. SessionMock.InSequence(seq).Setup(p => p.UnRegisterMessage("SSH_MSG_USERAUTH_FAILURE"));
  126. SessionMock.InSequence(seq).Setup(p => p.UnRegisterMessage("SSH_MSG_USERAUTH_SUCCESS"));
  127. SessionMock.InSequence(seq).Setup(p => p.UnRegisterMessage("SSH_MSG_USERAUTH_BANNER"));
  128. }
  129. protected override void Arrange()
  130. {
  131. base.Arrange();
  132. _clientAuthentication = new ClientAuthentication(_partialSuccessLimit);
  133. }
  134. protected override void Act()
  135. {
  136. try
  137. {
  138. _clientAuthentication.Authenticate(ConnectionInfoMock.Object, SessionMock.Object);
  139. Assert.Fail();
  140. }
  141. catch (SshAuthenticationException ex)
  142. {
  143. _actualException = ex;
  144. }
  145. }
  146. [TestMethod]
  147. public void AuthenticateOnKeyboardInteractiveAuthenticationMethodShouldHaveBeenInvokedOnce()
  148. {
  149. KeyboardInteractiveAuthenticationMethodMock.Verify(p => p.Authenticate(SessionMock.Object), Times.Once);
  150. }
  151. [TestMethod]
  152. public void AuthenticateOnPublicKeyAuthenticationMethodShouldHaveBeenInvokedTwice()
  153. {
  154. PublicKeyAuthenticationMethodMock.Verify(p => p.Authenticate(SessionMock.Object), Times.Exactly(2));
  155. }
  156. [TestMethod]
  157. public void AuthenticateShouldThrowSshAuthenticationException()
  158. {
  159. Assert.IsNotNull(_actualException);
  160. Assert.IsNull(_actualException.InnerException);
  161. Assert.AreEqual("Permission denied (publickey).", _actualException.Message);
  162. }
  163. }
  164. }