diff --git a/src/Renci.SshNet/Common/AuthenticationPromptEventArgs.cs b/src/Renci.SshNet/Common/AuthenticationPromptEventArgs.cs
index 9c22c340c..3a2562ae1 100644
--- a/src/Renci.SshNet/Common/AuthenticationPromptEventArgs.cs
+++ b/src/Renci.SshNet/Common/AuthenticationPromptEventArgs.cs
@@ -14,7 +14,7 @@ public class AuthenticationPromptEventArgs : AuthenticationEventArgs
/// The instruction.
/// The language.
/// The information request prompts.
- public AuthenticationPromptEventArgs(string username, string instruction, string language, IEnumerable prompts)
+ public AuthenticationPromptEventArgs(string username, string instruction, string language, IReadOnlyList prompts)
: base(username)
{
Instruction = instruction;
@@ -35,6 +35,6 @@ public AuthenticationPromptEventArgs(string username, string instruction, string
///
/// Gets server information request prompts.
///
- public IEnumerable Prompts { get; }
+ public IReadOnlyList Prompts { get; }
}
}
diff --git a/src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs b/src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs
index 825809950..7169fabc0 100644
--- a/src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs
+++ b/src/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs
@@ -125,9 +125,19 @@ private void Session_UserAuthenticationInformationRequestReceived(object sender,
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
diff --git a/src/Renci.SshNet/Messages/Authentication/InformationRequestMessage.cs b/src/Renci.SshNet/Messages/Authentication/InformationRequestMessage.cs
index c887cc883..7110222ac 100644
--- a/src/Renci.SshNet/Messages/Authentication/InformationRequestMessage.cs
+++ b/src/Renci.SshNet/Messages/Authentication/InformationRequestMessage.cs
@@ -29,7 +29,7 @@ internal sealed class InformationRequestMessage : Message
///
/// Gets information request prompts.
///
- public IEnumerable Prompts { get; private set; }
+ public IReadOnlyList Prompts { get; private set; }
///
/// Called when type specific data need to be loaded.
diff --git a/test/Renci.SshNet.IntegrationTests/AuthenticationMethodFactory.cs b/test/Renci.SshNet.IntegrationTests/AuthenticationMethodFactory.cs
index 17e4c75b6..edb3e74d1 100644
--- a/test/Renci.SshNet.IntegrationTests/AuthenticationMethodFactory.cs
+++ b/test/Renci.SshNet.IntegrationTests/AuthenticationMethodFactory.cs
@@ -69,7 +69,7 @@ public PrivateKeyAuthenticationMethod CreateRegularUserPrivateKeyAuthenticationM
return new PrivateKeyAuthenticationMethod(Users.Regular.UserName, new PrivateKeyFile(memoryStream));
}
- public PasswordAuthenticationMethod CreateRegulatUserPasswordAuthenticationMethod()
+ public PasswordAuthenticationMethod CreateRegularUserPasswordAuthenticationMethod()
{
return new PasswordAuthenticationMethod(Users.Regular.UserName, Users.Regular.Password);
}
diff --git a/test/Renci.SshNet.IntegrationTests/AuthenticationTests.cs b/test/Renci.SshNet.IntegrationTests/AuthenticationTests.cs
index c3968e949..dd0a4f3d9 100644
--- a/test/Renci.SshNet.IntegrationTests/AuthenticationTests.cs
+++ b/test/Renci.SshNet.IntegrationTests/AuthenticationTests.cs
@@ -161,7 +161,7 @@ public void Multifactor_Password_ExceedsPartialSuccessLimit()
.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 @@ public void Multifactor_Password_MatchPartialSuccessLimit()
.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 @@ public void Multifactor_Password_Or_PublicKeyAndKeyboardInteractive()
.Restart();
var connectionInfo = _connectionInfoFactory.Create(_authenticationMethodFactory.CreateRegularUserPrivateKeyAuthenticationMethod(),
- _authenticationMethodFactory.CreateRegulatUserPasswordAuthenticationMethod());
+ _authenticationMethodFactory.CreateRegularUserPasswordAuthenticationMethod());
using (var client = new SftpClient(connectionInfo))
{
client.Connect();
@@ -243,7 +243,7 @@ public void Multifactor_PasswordAndPublicKey_Or_PasswordAndPassword()
.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 @@ public void Multifactor_PasswordAndPassword_Or_PublicKey()
.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 @@ public void Multifactor_Password_Or_Password()
.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 @@ public void KeyboardInteractiveConnectionInfo()
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}\"");
+ }
+ }
+ }
}
}