Selaa lähdekoodia

Fail with a friendlier error message when response has not been set (#1245)

Co-authored-by: Wojciech Nagórski <wojtpl2@gmail.com>
Rob Hague 1 vuosi sitten
vanhempi
sitoutus
a027c76d7a

+ 2 - 2
src/Renci.SshNet/Common/AuthenticationPromptEventArgs.cs

@@ -14,7 +14,7 @@ namespace Renci.SshNet.Common
         /// <param name="instruction">The instruction.</param>
         /// <param name="language">The language.</param>
         /// <param name="prompts">The information request prompts.</param>
-        public AuthenticationPromptEventArgs(string username, string instruction, string language, IEnumerable<AuthenticationPrompt> prompts)
+        public AuthenticationPromptEventArgs(string username, string instruction, string language, IReadOnlyList<AuthenticationPrompt> prompts)
             : base(username)
         {
             Instruction = instruction;
@@ -35,6 +35,6 @@ namespace Renci.SshNet.Common
         /// <summary>
         /// Gets server information request prompts.
         /// </summary>
-        public IEnumerable<AuthenticationPrompt> Prompts { get; }
+        public IReadOnlyList<AuthenticationPrompt> Prompts { get; }
     }
 }

+ 12 - 2
src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs

@@ -125,9 +125,19 @@ namespace Renci.SshNet
 
                         var informationResponse = new InformationResponseMessage();
 
-                        foreach (var response in from r in eventArgs.Prompts orderby r.Id ascending select r.Response)
+                        foreach (var prompt in eventArgs.Prompts.OrderBy(r => r.Id))
                         {
-                            informationResponse.Responses.Add(response);
+                            if (prompt.Response is null)
+                            {
+                                throw new SshAuthenticationException(
+                                    $"{nameof(AuthenticationPrompt)}.{nameof(prompt.Response)} is null for " +
+                                    $"prompt \"{prompt.Request}\". You can set this by subscribing to " +
+                                    $"{nameof(KeyboardInteractiveAuthenticationMethod)}.{nameof(AuthenticationPrompt)} " +
+                                    $"and inspecting the {nameof(AuthenticationPromptEventArgs.Prompts)} property " +
+                                    $"of the event args.");
+                            }
+
+                            informationResponse.Responses.Add(prompt.Response);
                         }
 
                         // Send information response message

+ 1 - 1
src/Renci.SshNet/Messages/Authentication/InformationRequestMessage.cs

@@ -29,7 +29,7 @@ namespace Renci.SshNet.Messages.Authentication
         /// <summary>
         /// Gets information request prompts.
         /// </summary>
-        public IEnumerable<AuthenticationPrompt> Prompts { get; private set; }
+        public IReadOnlyList<AuthenticationPrompt> Prompts { get; private set; }
 
         /// <summary>
         /// Called when type specific data need to be loaded.

+ 1 - 1
test/Renci.SshNet.IntegrationTests/AuthenticationMethodFactory.cs

@@ -69,7 +69,7 @@
             return new PrivateKeyAuthenticationMethod(Users.Regular.UserName, new PrivateKeyFile(memoryStream));
         }
 
-        public PasswordAuthenticationMethod CreateRegulatUserPasswordAuthenticationMethod()
+        public PasswordAuthenticationMethod CreateRegularUserPasswordAuthenticationMethod()
         {
             return new PasswordAuthenticationMethod(Users.Regular.UserName, Users.Regular.Password);
         }

+ 38 - 8
test/Renci.SshNet.IntegrationTests/AuthenticationTests.cs

@@ -161,7 +161,7 @@ namespace Renci.SshNet.IntegrationTests
                              .Update()
                              .Restart();
 
-            var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegulatUserPasswordAuthenticationMethod());
+            var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod());
             using (var client = new SftpClient(connectionInfo))
             {
                 try
@@ -187,7 +187,7 @@ namespace Renci.SshNet.IntegrationTests
                              .Update()
                              .Restart();
 
-            var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegulatUserPasswordAuthenticationMethod());
+            var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod());
             using (var client = new SftpClient(connectionInfo))
             {
                 client.Connect();
@@ -205,7 +205,7 @@ namespace Renci.SshNet.IntegrationTests
                              .Restart();
 
             var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethod(),
-                                                               _authenticationMethodFactory.CreateRegulatUserPasswordAuthenticationMethod());
+                                                               _authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod());
             using (var client = new SftpClient(connectionInfo))
             {
                 client.Connect();
@@ -243,7 +243,7 @@ namespace Renci.SshNet.IntegrationTests
                              .Update()
                              .Restart();
 
-            var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegulatUserPasswordAuthenticationMethod(),
+            var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod(),
                                                                _authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethodWithBadKey());
             using (var client = new SftpClient(connectionInfo))
             {
@@ -275,14 +275,14 @@ namespace Renci.SshNet.IntegrationTests
                              .Update()
                              .Restart();
 
-            var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegulatUserPasswordAuthenticationMethod(),
+            var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod(),
                                                                _authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethodWithBadKey());
             using (var client = new SftpClient(connectionInfo))
             {
                 client.Connect();
             }
 
-            connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegulatUserPasswordAuthenticationMethod());
+            connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod());
             using (var client = new SftpClient(connectionInfo))
             {
                 client.Connect();
@@ -297,13 +297,13 @@ namespace Renci.SshNet.IntegrationTests
                              .Update()
                              .Restart();
 
-            var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegulatUserPasswordAuthenticationMethod());
+            var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod());
             using (var client = new SftpClient(connectionInfo))
             {
                 client.Connect();
             }
 
-            connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegulatUserPasswordAuthenticationMethod(),
+            connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod(),
                                                            _authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethodWithBadKey());
             using (var client = new SftpClient(connectionInfo))
             {
@@ -423,5 +423,35 @@ namespace Renci.SshNet.IntegrationTests
             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}\"");
+                }
+            }
+        }
     }
 }