<PackageReference Include="SSH.NET" Version="2016.1.0-beta2" />

ClientAuthentication

using Renci.SshNet.Common; using System; using System.Collections.Generic; using System.Linq; namespace Renci.SshNet { internal class ClientAuthentication : IClientAuthentication { private class AuthenticationState { private readonly IList<IAuthenticationMethod> _supportedAuthenticationMethods; public IList<IAuthenticationMethod> ExecutedAuthenticationMethods { get; set; } public IList<IAuthenticationMethod> FailedAuthenticationMethods { get; set; } public IEnumerable<IAuthenticationMethod> SupportedAuthenticationMethods => _supportedAuthenticationMethods; public AuthenticationState(IList<IAuthenticationMethod> supportedAuthenticationMethods) { _supportedAuthenticationMethods = supportedAuthenticationMethods; ExecutedAuthenticationMethods = new List<IAuthenticationMethod>(); FailedAuthenticationMethods = new List<IAuthenticationMethod>(); } } public void Authenticate(IConnectionInfoInternal connectionInfo, ISession session) { if (connectionInfo == null) throw new ArgumentNullException("connectionInfo"); if (session == null) throw new ArgumentNullException("session"); session.RegisterMessage("SSH_MSG_USERAUTH_FAILURE"); session.RegisterMessage("SSH_MSG_USERAUTH_SUCCESS"); session.RegisterMessage("SSH_MSG_USERAUTH_BANNER"); session.UserAuthenticationBannerReceived += connectionInfo.UserAuthenticationBannerReceived; try { SshAuthenticationException authenticationException = null; IAuthenticationMethod authenticationMethod = connectionInfo.CreateNoneAuthenticationMethod(); if (authenticationMethod.Authenticate(session) != 0 && !TryAuthenticate(session, new AuthenticationState(connectionInfo.AuthenticationMethods), authenticationMethod.AllowedAuthentications, ref authenticationException)) throw authenticationException; } finally { session.UserAuthenticationBannerReceived -= connectionInfo.UserAuthenticationBannerReceived; session.UnRegisterMessage("SSH_MSG_USERAUTH_FAILURE"); session.UnRegisterMessage("SSH_MSG_USERAUTH_SUCCESS"); session.UnRegisterMessage("SSH_MSG_USERAUTH_BANNER"); } } private static bool TryAuthenticate(ISession session, AuthenticationState authenticationState, ICollection<string> allowedAuthenticationMethods, ref SshAuthenticationException authenticationException) { if (allowedAuthenticationMethods.Count == 0) { authenticationException = new SshAuthenticationException("No authentication methods defined on SSH server."); return false; } IAuthenticationMethod[] array = (from a in authenticationState.SupportedAuthenticationMethods where allowedAuthenticationMethods.Contains(a.Name) select a).ToArray(); if (array.Length == 0) { authenticationException = new SshAuthenticationException(string.Format("No suitable authentication method found to complete authentication ({0}).", string.Join(",", allowedAuthenticationMethods.ToArray()))); return false; } foreach (IAuthenticationMethod orderedAuthenticationMethod in GetOrderedAuthenticationMethods(authenticationState, array)) { if (!authenticationState.FailedAuthenticationMethods.Contains(orderedAuthenticationMethod)) { if (!authenticationState.ExecutedAuthenticationMethods.Contains(orderedAuthenticationMethod)) authenticationState.ExecutedAuthenticationMethods.Add(orderedAuthenticationMethod); AuthenticationResult authenticationResult = orderedAuthenticationMethod.Authenticate(session); switch (authenticationResult) { case AuthenticationResult.PartialSuccess: if (TryAuthenticate(session, authenticationState, orderedAuthenticationMethod.AllowedAuthentications, ref authenticationException)) authenticationResult = AuthenticationResult.Success; break; case AuthenticationResult.Failure: authenticationState.FailedAuthenticationMethods.Add(orderedAuthenticationMethod); authenticationException = new SshAuthenticationException($"""{orderedAuthenticationMethod.Name}"""); break; case AuthenticationResult.Success: authenticationException = null; break; } if (authenticationResult == AuthenticationResult.Success) return true; } } return false; } private static IEnumerable<IAuthenticationMethod> GetOrderedAuthenticationMethods(AuthenticationState authenticationState, IAuthenticationMethod[] matchingAuthenticationMethods) { List<IAuthenticationMethod> skippedAuthenticationMethods = new List<IAuthenticationMethod>(); foreach (IAuthenticationMethod authenticationMethod in matchingAuthenticationMethods) { if (authenticationState.ExecutedAuthenticationMethods.Contains(authenticationMethod)) skippedAuthenticationMethods.Add(authenticationMethod); else yield return authenticationMethod; } List<IAuthenticationMethod>.Enumerator enumerator = skippedAuthenticationMethods.GetEnumerator(); try { while (enumerator.MoveNext()) { IAuthenticationMethod current = enumerator.Current; yield return current; } } finally { ((IDisposable)enumerator).Dispose(); } enumerator = default(List<IAuthenticationMethod>.Enumerator); } } }