<PackageReference Include="SSH.NET" Version="2020.0.2" />

KeyboardInteractiveAuthenticationMethod

Provides functionality to perform keyboard interactive authentication.
using Renci.SshNet.Abstractions; using Renci.SshNet.Common; using Renci.SshNet.Messages; using Renci.SshNet.Messages.Authentication; using System; using System.Linq; using System.Threading; namespace Renci.SshNet { public class KeyboardInteractiveAuthenticationMethod : AuthenticationMethod, IDisposable { private AuthenticationResult _authenticationResult = AuthenticationResult.Failure; private Session _session; private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false); private Exception _exception; private readonly RequestMessage _requestMessage; private bool _isDisposed; public override string Name => _requestMessage.MethodName; public event EventHandler<AuthenticationPromptEventArgs> AuthenticationPrompt; public KeyboardInteractiveAuthenticationMethod(string username) : base(username) { _requestMessage = new RequestMessageKeyboardInteractive(ServiceName.Connection, username); } public override AuthenticationResult Authenticate(Session session) { _session = session; session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived; session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived; session.UserAuthenticationInformationRequestReceived += Session_UserAuthenticationInformationRequestReceived; session.RegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST"); try { session.SendMessage(_requestMessage); session.WaitOnHandle(_authenticationCompleted); } finally { session.UnRegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST"); session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived; session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived; session.UserAuthenticationInformationRequestReceived -= Session_UserAuthenticationInformationRequestReceived; } if (_exception != null) throw _exception; return _authenticationResult; } private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs<SuccessMessage> e) { _authenticationResult = AuthenticationResult.Success; _authenticationCompleted.Set(); } private void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs<FailureMessage> e) { if (e.Message.PartialSuccess) _authenticationResult = AuthenticationResult.PartialSuccess; else _authenticationResult = AuthenticationResult.Failure; base.AllowedAuthentications = e.Message.AllowedAuthentications; _authenticationCompleted.Set(); } private void Session_UserAuthenticationInformationRequestReceived(object sender, MessageEventArgs<InformationRequestMessage> e) { InformationRequestMessage message = e.Message; AuthenticationPromptEventArgs eventArgs = new AuthenticationPromptEventArgs(base.Username, message.Instruction, message.Language, message.Prompts); ThreadAbstraction.ExecuteThread(delegate { try { if (this.AuthenticationPrompt != null) this.AuthenticationPrompt(this, eventArgs); InformationResponseMessage informationResponseMessage = new InformationResponseMessage(); foreach (string item in from r in eventArgs.Prompts orderby r.Id select r.Response) { informationResponseMessage.Responses.Add(item); } _session.SendMessage(informationResponseMessage); } catch (Exception exception) { _exception = exception; _authenticationCompleted.Set(); } }); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!_isDisposed && disposing) { EventWaitHandle authenticationCompleted = _authenticationCompleted; if (authenticationCompleted != null) { _authenticationCompleted = null; authenticationCompleted.Dispose(); } _isDisposed = true; } } ~KeyboardInteractiveAuthenticationMethod() { Dispose(false); } } }