using System; using System.Collections.Generic; using System.Linq; using System.Text; using Renci.SshNet.Abstractions; using Renci.SshNet.Security; using Renci.SshNet.Messages.Connection; using Renci.SshNet.Common; using Renci.SshNet.Messages.Authentication; using Renci.SshNet.Security.Cryptography.Ciphers.Modes; using Renci.SshNet.Security.Cryptography.Ciphers; namespace Renci.SshNet { /// /// Represents remote connection information class. /// /// /// This class is NOT thread-safe. Do not use the same with multiple /// client instances. /// public class ConnectionInfo : IConnectionInfoInternal { internal static int DefaultPort = 22; /// /// Gets supported key exchange algorithms for this connection. /// public IDictionary KeyExchangeAlgorithms { get; private set; } /// /// Gets supported encryptions for this connection. /// public IDictionary Encryptions { get; private set; } /// /// Gets supported hash algorithms for this connection. /// public IDictionary HmacAlgorithms { get; private set; } /// /// Gets supported host key algorithms for this connection. /// public IDictionary> HostKeyAlgorithms { get; private set; } /// /// Gets supported authentication methods for this connection. /// public IList AuthenticationMethods { get; private set; } /// /// Gets supported compression algorithms for this connection. /// public IDictionary CompressionAlgorithms { get; private set; } /// /// Gets the supported channel requests for this connection. /// /// /// The supported channel requests for this connection. /// public IDictionary ChannelRequests { get; private set; } /// /// Gets a value indicating whether connection is authenticated. /// /// /// true if connection is authenticated; otherwise, false. /// public bool IsAuthenticated { get; private set; } /// /// Gets connection host. /// public string Host { get; private set; } /// /// Gets connection port. /// /// /// The connection port. The default value is 22. /// public int Port { get; private set; } /// /// Gets connection username. /// public string Username { get; private set; } /// /// Gets proxy type. /// /// /// The type of the proxy. /// public ProxyTypes ProxyType { get; private set; } /// /// Gets proxy connection host. /// public string ProxyHost { get; private set; } /// /// Gets proxy connection port. /// public int ProxyPort { get; private set; } /// /// Gets proxy connection username. /// public string ProxyUsername { get; private set; } /// /// Gets proxy connection password. /// public string ProxyPassword { get; private set; } /// /// Gets or sets connection timeout. /// /// /// The connection timeout. The default value is 30 seconds. /// /// /// /// public TimeSpan Timeout { get; set; } /// /// Gets or sets the character encoding. /// /// /// The character encoding. The default is . /// public Encoding Encoding { get; set; } /// /// Gets or sets number of retry attempts when session channel creation failed. /// /// /// The number of retry attempts when session channel creation failed. The default /// value is 10. /// public int RetryAttempts { get; set; } /// /// Gets or sets maximum number of session channels to be open simultaneously. /// /// /// The maximum number of session channels to be open simultaneously. The default /// value is 10. /// public int MaxSessions { get; set; } /// /// Occurs when authentication banner is sent by the server. /// /// /// /// public event EventHandler AuthenticationBanner; /// /// Gets the current key exchange algorithm. /// public string CurrentKeyExchangeAlgorithm { get; internal set; } /// /// Gets the current server encryption. /// public string CurrentServerEncryption { get; internal set; } /// /// Gets the current client encryption. /// public string CurrentClientEncryption { get; internal set; } /// /// Gets the current server hash algorithm. /// public string CurrentServerHmacAlgorithm { get; internal set; } /// /// Gets the current client hash algorithm. /// public string CurrentClientHmacAlgorithm { get; internal set; } /// /// Gets the current host key algorithm. /// public string CurrentHostKeyAlgorithm { get; internal set; } /// /// Gets the current server compression algorithm. /// public string CurrentServerCompressionAlgorithm { get; internal set; } /// /// Gets the server version. /// public string ServerVersion { get; internal set; } /// /// Get the client version. /// public string ClientVersion { get; internal set; } /// /// Gets the current client compression algorithm. /// public string CurrentClientCompressionAlgorithm { get; internal set; } /// /// Initializes a new instance of the class. /// /// The host. /// The username. /// The authentication methods. /// is null. /// is a zero-length string. /// is null, a zero-length string or contains only whitespace characters. /// is null. /// No specified. public ConnectionInfo(string host, string username, params AuthenticationMethod[] authenticationMethods) : this(host, DefaultPort, username, ProxyTypes.None, null, 0, null, null, authenticationMethods) { } /// /// Initializes a new instance of the class. /// /// The host. /// The port. /// The username. /// The authentication methods. /// is null. /// is null, a zero-length string or contains only whitespace characters. /// is not within and . /// is null. /// No specified. public ConnectionInfo(string host, int port, string username, params AuthenticationMethod[] authenticationMethods) : this(host, port, username, ProxyTypes.None, null, 0, null, null, authenticationMethods) { } /// /// Initializes a new instance of the class. /// /// Connection host. /// Connection port. /// Connection username. /// Type of the proxy. /// The proxy host. /// The proxy port. /// The proxy username. /// The proxy password. /// The authentication methods. /// is null. /// is null, a zero-length string or contains only whitespace characters. /// is not within and . /// is not and is null. /// is not and is not within and . /// is null. /// No specified. public ConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params AuthenticationMethod[] authenticationMethods) { if (host == null) throw new ArgumentNullException("host"); port.ValidatePort("port"); if (username == null) throw new ArgumentNullException("username"); if (username.All(char.IsWhiteSpace)) throw new ArgumentException("Cannot be empty or contain only whitespace.", "username"); if (proxyType != ProxyTypes.None) { if (proxyHost == null) throw new ArgumentNullException("proxyHost"); proxyPort.ValidatePort("proxyPort"); } if (authenticationMethods == null) throw new ArgumentNullException("authenticationMethods"); if (authenticationMethods.Length == 0) throw new ArgumentException("At least one authentication method should be specified.", "authenticationMethods"); // Set default connection values Timeout = TimeSpan.FromSeconds(30); RetryAttempts = 10; MaxSessions = 10; Encoding = Encoding.UTF8; KeyExchangeAlgorithms = new Dictionary { {"diffie-hellman-group-exchange-sha256", typeof (KeyExchangeDiffieHellmanGroupExchangeSha256)}, {"diffie-hellman-group-exchange-sha1", typeof (KeyExchangeDiffieHellmanGroupExchangeSha1)}, {"diffie-hellman-group14-sha1", typeof (KeyExchangeDiffieHellmanGroup14Sha1)}, {"diffie-hellman-group1-sha1", typeof (KeyExchangeDiffieHellmanGroup1Sha1)}, //{"ecdh-sha2-nistp256", typeof(KeyExchangeEllipticCurveDiffieHellman)}, //{"ecdh-sha2-nistp256", typeof(...)}, //{"ecdh-sha2-nistp384", typeof(...)}, //{"ecdh-sha2-nistp521", typeof(...)}, //"gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==" - WinSSHD //"gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==" - WinSSHD }; Encryptions = new Dictionary { {"aes256-ctr", new CipherInfo(256, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))}, {"3des-cbc", new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), null))}, {"aes128-cbc", new CipherInfo(128, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))}, {"aes192-cbc", new CipherInfo(192, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))}, {"aes256-cbc", new CipherInfo(256, (key, iv) => new AesCipher(key, new CbcCipherMode(iv), null))}, {"blowfish-cbc", new CipherInfo(128, (key, iv) => new BlowfishCipher(key, new CbcCipherMode(iv), null))}, {"twofish-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))}, {"twofish192-cbc", new CipherInfo(192, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))}, {"twofish128-cbc", new CipherInfo(128, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))}, {"twofish256-cbc", new CipherInfo(256, (key, iv) => new TwofishCipher(key, new CbcCipherMode(iv), null))}, ////{"serpent256-cbc", typeof(CipherSerpent256CBC)}, ////{"serpent192-cbc", typeof(...)}, ////{"serpent128-cbc", typeof(...)}, {"arcfour", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, false))}, {"arcfour128", new CipherInfo(128, (key, iv) => new Arc4Cipher(key, true))}, {"arcfour256", new CipherInfo(256, (key, iv) => new Arc4Cipher(key, true))}, ////{"idea-cbc", typeof(...)}, {"cast128-cbc", new CipherInfo(128, (key, iv) => new CastCipher(key, new CbcCipherMode(iv), null))}, ////{"rijndael-cbc@lysator.liu.se", typeof(...)}, {"aes128-ctr", new CipherInfo(128, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))}, {"aes192-ctr", new CipherInfo(192, (key, iv) => new AesCipher(key, new CtrCipherMode(iv), null))}, }; HmacAlgorithms = new Dictionary { {"hmac-md5", new HashInfo(16*8, CryptoAbstraction.CreateHMACMD5)}, {"hmac-md5-96", new HashInfo(16*8, key => CryptoAbstraction.CreateHMACMD5(key, 96))}, {"hmac-sha1", new HashInfo(20*8, CryptoAbstraction.CreateHMACSHA1)}, {"hmac-sha1-96", new HashInfo(20*8, key => CryptoAbstraction.CreateHMACSHA1(key, 96))}, {"hmac-sha2-256", new HashInfo(32*8, CryptoAbstraction.CreateHMACSHA256)}, {"hmac-sha2-256-96", new HashInfo(32*8, key => CryptoAbstraction.CreateHMACSHA256(key, 96))}, {"hmac-sha2-512", new HashInfo(64 * 8, CryptoAbstraction.CreateHMACSHA512)}, {"hmac-sha2-512-96", new HashInfo(64 * 8, key => CryptoAbstraction.CreateHMACSHA512(key, 96))}, //{"umac-64@openssh.com", typeof(HMacSha1)}, {"hmac-ripemd160", new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160)}, {"hmac-ripemd160@openssh.com", new HashInfo(160, CryptoAbstraction.CreateHMACRIPEMD160)}, //{"none", typeof(...)}, }; HostKeyAlgorithms = new Dictionary> { {"ssh-rsa", data => new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data)}, {"ssh-dss", data => new KeyHostAlgorithm("ssh-dss", new DsaKey(), data)}, //{"ecdsa-sha2-nistp256 "} //{"x509v3-sign-rsa", () => { ... }, //{"x509v3-sign-dss", () => { ... }, //{"spki-sign-rsa", () => { ... }, //{"spki-sign-dss", () => { ... }, //{"pgp-sign-rsa", () => { ... }, //{"pgp-sign-dss", () => { ... }, }; CompressionAlgorithms = new Dictionary { //{"zlib@openssh.com", typeof(ZlibOpenSsh)}, //{"zlib", typeof(Zlib)}, {"none", null}, }; ChannelRequests = new Dictionary { {EnvironmentVariableRequestInfo.Name, new EnvironmentVariableRequestInfo()}, {ExecRequestInfo.Name, new ExecRequestInfo()}, {ExitSignalRequestInfo.Name, new ExitSignalRequestInfo()}, {ExitStatusRequestInfo.Name, new ExitStatusRequestInfo()}, {PseudoTerminalRequestInfo.Name, new PseudoTerminalRequestInfo()}, {ShellRequestInfo.Name, new ShellRequestInfo()}, {SignalRequestInfo.Name, new SignalRequestInfo()}, {SubsystemRequestInfo.Name, new SubsystemRequestInfo()}, {WindowChangeRequestInfo.Name, new WindowChangeRequestInfo()}, {X11ForwardingRequestInfo.Name, new X11ForwardingRequestInfo()}, {XonXoffRequestInfo.Name, new XonXoffRequestInfo()}, {EndOfWriteRequestInfo.Name, new EndOfWriteRequestInfo()}, {KeepAliveRequestInfo.Name, new KeepAliveRequestInfo()}, }; Host = host; Port = port; Username = username; ProxyType = proxyType; ProxyHost = proxyHost; ProxyPort = proxyPort; ProxyUsername = proxyUsername; ProxyPassword = proxyPassword; AuthenticationMethods = authenticationMethods; } /// /// Authenticates the specified session. /// /// The session to be authenticated. /// The factory to use for creating new services. /// is null. /// is null. /// No suitable authentication method found to complete authentication, or permission denied. internal void Authenticate(ISession session, IServiceFactory serviceFactory) { if (serviceFactory == null) throw new ArgumentNullException("serviceFactory"); IsAuthenticated = false; var clientAuthentication = serviceFactory.CreateClientAuthentication(); clientAuthentication.Authenticate(this, session); IsAuthenticated = true; } /// /// Signals that an authentication banner message was received from the server. /// /// The session in which the banner message was received. /// The banner message.{ void IConnectionInfoInternal.UserAuthenticationBannerReceived(object sender, MessageEventArgs e) { var authenticationBanner = AuthenticationBanner; if (authenticationBanner != null) { authenticationBanner(this, new AuthenticationBannerEventArgs(Username, e.Message.Message, e.Message.Language)); } } IAuthenticationMethod IConnectionInfoInternal.CreateNoneAuthenticationMethod() { return new NoneAuthenticationMethod(Username); } IList IConnectionInfoInternal.AuthenticationMethods { get { return AuthenticationMethods.Cast().ToList(); } } } }