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

ClientAuthentication

using Renci.SshNet.Common; using System; using System.Collections.Generic; 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 IList<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, string[] allowedAuthenticationMethods, ref SshAuthenticationException authenticationException) { if (allowedAuthenticationMethods.Length == 0) { authenticationException = new SshAuthenticationException("No authentication methods defined on SSH server."); return false; } List<IAuthenticationMethod> allowedAuthenticationMethodsThatAreSupported = GetAllowedAuthenticationMethodsThatAreSupported(authenticationState, allowedAuthenticationMethods); if (allowedAuthenticationMethodsThatAreSupported.Count == 0) { authenticationException = new SshAuthenticationException(string.Format("No suitable authentication method found to complete authentication ({0}).", string.Join(",", allowedAuthenticationMethods))); return false; } foreach (IAuthenticationMethod orderedAuthenticationMethod in GetOrderedAuthenticationMethods(authenticationState, allowedAuthenticationMethodsThatAreSupported)) { 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 List<IAuthenticationMethod> GetAllowedAuthenticationMethodsThatAreSupported(AuthenticationState authenticationState, string[] allowedAuthenticationMethods) { List<IAuthenticationMethod> list = new List<IAuthenticationMethod>(); foreach (IAuthenticationMethod supportedAuthenticationMethod in authenticationState.SupportedAuthenticationMethods) { string name = supportedAuthenticationMethod.Name; for (int i = 0; i < allowedAuthenticationMethods.Length; i++) { if (allowedAuthenticationMethods[i] == name) { list.Add(supportedAuthenticationMethod); break; } } } return list; } private static IEnumerable<IAuthenticationMethod> GetOrderedAuthenticationMethods(AuthenticationState authenticationState, List<IAuthenticationMethod> matchingAuthenticationMethods) { List<IAuthenticationMethod> skippedAuthenticationMethods = new List<IAuthenticationMethod>(); for (int i = 0; i < matchingAuthenticationMethods.Count; i++) { IAuthenticationMethod authenticationMethod = matchingAuthenticationMethods[i]; 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); } } }