From ccda04e6f16e104c5a9ccac2aa44a1c453320be2 Mon Sep 17 00:00:00 2001 From: olegkap_cp Date: Wed, 15 Dec 2010 21:40:23 +0000 Subject: [PATCH] IDisposable interface refactoring Remove Settings class and specify suported algorithm per session to allow in future to modify supported algorithms per connection --- .../Renci.SshClient/Channels/Channel.cs | 12 +- .../Channels/ChannelDirectTcpip.cs | 5 - .../Channels/ChannelForwardedTcpip.cs | 6 +- .../Channels/ChannelSession.cs | 26 ++-- .../Renci.SshClient/Common/Extensions.cs | 14 +- .../Renci.SshClient/Compression/Compressor.cs | 2 +- .../Renci.SshClient/Compression/Zlib.cs | 5 +- .../Compression/ZlibOpenSsh.cs | 5 +- .../Renci.SshClient/ForwardedPortRemote.cs | 8 +- .../Renci.SshClient/Renci.SshClient.csproj | 3 + .../Renci.SshClient/Security/Cipher.cs | 29 +++- .../Renci.SshClient/Security/CipherAES.cs | 35 ++--- .../Security/CipherTripleDES.cs | 29 +--- .../Renci.SshClient/Security/HMac.cs | 69 +++++++++ .../Renci.SshClient/Security/HMacMD5.cs | 20 +++ .../Renci.SshClient/Security/HMacSha1.cs | 21 +++ .../Security/KeyExchangeAlgorithm.cs | 73 +++++++--- .../Security/KeyExchangeDiffieHellman.cs | 4 +- .../Security/UserAuthentication.cs | 2 +- .../Security/UserAuthenticationHost.cs | 10 -- .../Security/UserAuthenticationNone.cs | 31 +--- .../Security/UserAuthenticationPassword.cs | 31 +--- .../Security/UserAuthenticationPublicKey.cs | 33 +---- Renci.SshClient/Renci.SshClient/Session.cs | 136 +++++++++++++----- Renci.SshClient/Renci.SshClient/Settings.cs | 80 +++++------ .../Renci.SshClient/Sftp/SftpAsyncResult.cs | 2 +- .../Renci.SshClient/Sftp/SftpSession.cs | 8 +- .../Renci.SshClient/SshBaseClient.cs | 9 +- Renci.SshClient/Renci.SshClient/SshCommand.cs | 8 +- 29 files changed, 423 insertions(+), 293 deletions(-) create mode 100644 Renci.SshClient/Renci.SshClient/Security/HMac.cs create mode 100644 Renci.SshClient/Renci.SshClient/Security/HMacMD5.cs create mode 100644 Renci.SshClient/Renci.SshClient/Security/HMacSha1.cs diff --git a/Renci.SshClient/Renci.SshClient/Channels/Channel.cs b/Renci.SshClient/Renci.SshClient/Channels/Channel.cs index ff11ce1e..8ef4b09b 100644 --- a/Renci.SshClient/Renci.SshClient/Channels/Channel.cs +++ b/Renci.SshClient/Renci.SshClient/Channels/Channel.cs @@ -457,9 +457,7 @@ namespace Renci.SshClient.Channels #region IDisposable Members - protected abstract void OnDisposing(); - - private bool disposed = false; + private bool _isDisposed = false; public void Dispose() { @@ -468,10 +466,10 @@ namespace Renci.SshClient.Channels GC.SuppressFinalize(this); } - private void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. - if (!this.disposed) + if (!this._isDisposed) { // If disposing equals true, dispose all managed // and unmanaged resources. @@ -494,12 +492,10 @@ namespace Renci.SshClient.Channels { this._disconnectedWaitHandle.Dispose(); } - - this.OnDisposing(); } // Note disposing has been done. - disposed = true; + _isDisposed = true; } } diff --git a/Renci.SshClient/Renci.SshClient/Channels/ChannelDirectTcpip.cs b/Renci.SshClient/Renci.SshClient/Channels/ChannelDirectTcpip.cs index 048b491c..636a4846 100644 --- a/Renci.SshClient/Renci.SshClient/Channels/ChannelDirectTcpip.cs +++ b/Renci.SshClient/Renci.SshClient/Channels/ChannelDirectTcpip.cs @@ -149,10 +149,5 @@ namespace Renci.SshClient.Channels this._channelEof.Set(); } - - protected override void OnDisposing() - { - - } } } diff --git a/Renci.SshClient/Renci.SshClient/Channels/ChannelForwardedTcpip.cs b/Renci.SshClient/Renci.SshClient/Channels/ChannelForwardedTcpip.cs index 538b57a2..a320150f 100644 --- a/Renci.SshClient/Renci.SshClient/Channels/ChannelForwardedTcpip.cs +++ b/Renci.SshClient/Renci.SshClient/Channels/ChannelForwardedTcpip.cs @@ -121,13 +121,15 @@ namespace Renci.SshClient.Channels this._socket.Send(data.GetSshBytes().ToArray()); } - - protected override void OnDisposing() + protected override void Dispose(bool disposing) { + base.Dispose(disposing); + if (this._socket != null) { this._socket.Close(); } } + } } diff --git a/Renci.SshClient/Renci.SshClient/Channels/ChannelSession.cs b/Renci.SshClient/Renci.SshClient/Channels/ChannelSession.cs index 85397292..d1e4876e 100644 --- a/Renci.SshClient/Renci.SshClient/Channels/ChannelSession.cs +++ b/Renci.SshClient/Renci.SshClient/Channels/ChannelSession.cs @@ -254,17 +254,6 @@ namespace Renci.SshClient.Channels this._channelRequestResponse.Set(); } - /// - /// Called when object is being disposed. - /// - protected override void OnDisposing() - { - if (this._channelOpenResponseWaitHandle != null) - { - this._channelOpenResponseWaitHandle.Dispose(); - } - } - /// /// Sends the channel open message. /// @@ -278,5 +267,20 @@ namespace Renci.SshClient.Channels this.SendMessage(new ChannelOpenMessage(this.LocalChannelNumber, this.LocalWindowSize, this.PacketSize, new SessionChannelOpenInfo())); } } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (this._channelOpenResponseWaitHandle != null) + { + this._channelOpenResponseWaitHandle.Dispose(); + } + + if (this._channelRequestResponse != null) + { + this._channelRequestResponse.Dispose(); + } + } } } diff --git a/Renci.SshClient/Renci.SshClient/Common/Extensions.cs b/Renci.SshClient/Renci.SshClient/Common/Extensions.cs index bd2d17f7..fa87158a 100644 --- a/Renci.SshClient/Renci.SshClient/Common/Extensions.cs +++ b/Renci.SshClient/Renci.SshClient/Common/Extensions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System; namespace Renci.SshClient { @@ -65,7 +66,6 @@ namespace Renci.SshClient return IsEqualTo(value, compareList, null); } - public static void DebugPrint(this IEnumerable bytes) { foreach (var b in bytes) @@ -106,6 +106,16 @@ namespace Renci.SshClient } } - + /// + /// Creates the instance of the type specified by the string. + /// + /// + /// The name. + /// + internal static T CreateInstance(this string name) where T : class + { + var type = Type.GetType(name); + return Activator.CreateInstance(type) as T; + } } } diff --git a/Renci.SshClient/Renci.SshClient/Compression/Compressor.cs b/Renci.SshClient/Renci.SshClient/Compression/Compressor.cs index ea52849c..e4aef268 100644 --- a/Renci.SshClient/Renci.SshClient/Compression/Compressor.cs +++ b/Renci.SshClient/Renci.SshClient/Compression/Compressor.cs @@ -6,7 +6,7 @@ namespace Renci.SshClient.Compression { protected Session Session { get; private set; } - public Compressor(Session session) + public virtual void Init(Session session) { this.Session = session; } diff --git a/Renci.SshClient/Renci.SshClient/Compression/Zlib.cs b/Renci.SshClient/Renci.SshClient/Compression/Zlib.cs index 34851682..d1873399 100644 --- a/Renci.SshClient/Renci.SshClient/Compression/Zlib.cs +++ b/Renci.SshClient/Renci.SshClient/Compression/Zlib.cs @@ -12,9 +12,10 @@ namespace Renci.SshClient.Compression get { return "zlib"; } } - public Zlib(Session session) - : base(session) + public override void Init(Session session) { + base.Init(session); + session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived; } diff --git a/Renci.SshClient/Renci.SshClient/Compression/ZlibOpenSsh.cs b/Renci.SshClient/Renci.SshClient/Compression/ZlibOpenSsh.cs index 5f6e7713..7fafafdd 100644 --- a/Renci.SshClient/Renci.SshClient/Compression/ZlibOpenSsh.cs +++ b/Renci.SshClient/Renci.SshClient/Compression/ZlibOpenSsh.cs @@ -12,9 +12,10 @@ namespace Renci.SshClient.Compression get { return "zlib@openssh.org"; } } - public ZlibOpenSsh(Session session) - : base(session) + public override void Init(Session session) { + base.Init(session); + session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived; } diff --git a/Renci.SshClient/Renci.SshClient/ForwardedPortRemote.cs b/Renci.SshClient/Renci.SshClient/ForwardedPortRemote.cs index 2acf247c..9c132438 100644 --- a/Renci.SshClient/Renci.SshClient/ForwardedPortRemote.cs +++ b/Renci.SshClient/Renci.SshClient/ForwardedPortRemote.cs @@ -115,7 +115,7 @@ namespace Renci.SshClient #region IDisposable Members - private bool disposed = false; + private bool _isDisposed = false; public void Dispose() { @@ -124,10 +124,10 @@ namespace Renci.SshClient GC.SuppressFinalize(this); } - private void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. - if (!this.disposed) + if (!this._isDisposed) { // If disposing equals true, dispose all managed // and unmanaged resources. @@ -141,7 +141,7 @@ namespace Renci.SshClient } // Note disposing has been done. - disposed = true; + _isDisposed = true; } } diff --git a/Renci.SshClient/Renci.SshClient/Renci.SshClient.csproj b/Renci.SshClient/Renci.SshClient/Renci.SshClient.csproj index 93b13cba..63e8d89e 100644 --- a/Renci.SshClient/Renci.SshClient/Renci.SshClient.csproj +++ b/Renci.SshClient/Renci.SshClient/Renci.SshClient.csproj @@ -84,6 +84,9 @@ + + + diff --git a/Renci.SshClient/Renci.SshClient/Security/Cipher.cs b/Renci.SshClient/Renci.SshClient/Security/Cipher.cs index c310f13c..96515492 100644 --- a/Renci.SshClient/Renci.SshClient/Security/Cipher.cs +++ b/Renci.SshClient/Renci.SshClient/Security/Cipher.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using System.Linq; +using System; namespace Renci.SshClient.Security { - public abstract class Cipher + public abstract class Cipher : Algorithm, IDisposable { - public abstract string Name { get; } - public abstract int BlockSize { get; } public abstract int KeySize { get; } @@ -24,5 +23,29 @@ namespace Renci.SshClient.Security public abstract IEnumerable Encrypt(IEnumerable data); public abstract IEnumerable Decrypt(IEnumerable data); + + #region IDisposable Members + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + } + + ~Cipher() + { + // Do not re-create Dispose clean-up code here. + // Calling Dispose(false) is optimal in terms of + // readability and maintainability. + Dispose(false); + } + + #endregion + } } diff --git a/Renci.SshClient/Renci.SshClient/Security/CipherAES.cs b/Renci.SshClient/Renci.SshClient/Security/CipherAES.cs index 4e789dd7..1908ce12 100644 --- a/Renci.SshClient/Renci.SshClient/Security/CipherAES.cs +++ b/Renci.SshClient/Renci.SshClient/Security/CipherAES.cs @@ -5,7 +5,7 @@ using System.Security.Cryptography; namespace Renci.SshClient.Security { - internal abstract class CipherAES : Cipher, IDisposable + public abstract class CipherAES : Cipher { private SymmetricAlgorithm _algorithm; @@ -83,21 +83,12 @@ namespace Renci.SshClient.Security return output; } - #region IDisposable Members + private bool _isDisposed = false; - private bool disposed = false; - - public void Dispose() - { - Dispose(true); - - GC.SuppressFinalize(this); - } - - private void Dispose(bool disposing) + protected override void Dispose(bool disposing) { // Check to see if Dispose has already been called. - if (!this.disposed) + if (!this._isDisposed) { // If disposing equals true, dispose all managed // and unmanaged resources. @@ -111,22 +102,12 @@ namespace Renci.SshClient.Security } // Note disposing has been done. - disposed = true; + _isDisposed = true; } } - - ~CipherAES() - { - // Do not re-create Dispose clean-up code here. - // Calling Dispose(false) is optimal in terms of - // readability and maintainability. - Dispose(false); - } - - #endregion } - internal class CipherAES128CBC : CipherAES + public class CipherAES128CBC : CipherAES { public CipherAES128CBC() : base(128) @@ -135,7 +116,7 @@ namespace Renci.SshClient.Security } } - internal class CipherAES192CBC : CipherAES + public class CipherAES192CBC : CipherAES { public CipherAES192CBC() : base(192) @@ -144,7 +125,7 @@ namespace Renci.SshClient.Security } } - internal class CipherAES256CBC : CipherAES + public class CipherAES256CBC : CipherAES { public CipherAES256CBC() : base(256) diff --git a/Renci.SshClient/Renci.SshClient/Security/CipherTripleDES.cs b/Renci.SshClient/Renci.SshClient/Security/CipherTripleDES.cs index 06685fe0..babaffd0 100644 --- a/Renci.SshClient/Renci.SshClient/Security/CipherTripleDES.cs +++ b/Renci.SshClient/Renci.SshClient/Security/CipherTripleDES.cs @@ -5,7 +5,7 @@ using System.Security.Cryptography; namespace Renci.SshClient.Security { - internal class CipherTripleDES : Cipher, IDisposable + internal class CipherTripleDES : Cipher { private SymmetricAlgorithm _algorithm; @@ -79,21 +79,12 @@ namespace Renci.SshClient.Security return output; } - #region IDisposable Members + private bool _isDisposed = false; - private bool disposed = false; - - public void Dispose() - { - Dispose(true); - - GC.SuppressFinalize(this); - } - - private void Dispose(bool disposing) + protected override void Dispose(bool disposing) { // Check to see if Dispose has already been called. - if (!this.disposed) + if (!this._isDisposed) { // If disposing equals true, dispose all managed // and unmanaged resources. @@ -107,18 +98,8 @@ namespace Renci.SshClient.Security } // Note disposing has been done. - disposed = true; + _isDisposed = true; } } - - ~CipherTripleDES() - { - // Do not re-create Dispose clean-up code here. - // Calling Dispose(false) is optimal in terms of - // readability and maintainability. - Dispose(false); - } - - #endregion } } diff --git a/Renci.SshClient/Renci.SshClient/Security/HMac.cs b/Renci.SshClient/Renci.SshClient/Security/HMac.cs new file mode 100644 index 00000000..44160e7a --- /dev/null +++ b/Renci.SshClient/Renci.SshClient/Security/HMac.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Renci.SshClient.Security +{ + public abstract class HMac : Algorithm, IDisposable + { + protected System.Security.Cryptography.HMAC _hmac; + + public abstract void Init(IEnumerable key); + + internal byte[] ComputeHash(byte[] hashData) + { + return this._hmac.ComputeHash(hashData); + } + + public int HashSize + { + get + { + return this._hmac.HashSize; + } + } + + #region IDisposable Members + + private bool _disposed = false; + + public void Dispose() + { + Dispose(true); + + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + // Check to see if Dispose has already been called. + if (!this._disposed) + { + // If disposing equals true, dispose all managed + // and unmanaged resources. + if (disposing) + { + // Dispose managed resources. + if (this._hmac != null) + { + this._hmac.Dispose(); + } + } + + // Note disposing has been done. + this._disposed = true; + } + } + + ~HMac() + { + // Do not re-create Dispose clean-up code here. + // Calling Dispose(false) is optimal in terms of + // readability and maintainability. + Dispose(false); + } + + #endregion + } +} diff --git a/Renci.SshClient/Renci.SshClient/Security/HMacMD5.cs b/Renci.SshClient/Renci.SshClient/Security/HMacMD5.cs new file mode 100644 index 00000000..8e5089e2 --- /dev/null +++ b/Renci.SshClient/Renci.SshClient/Security/HMacMD5.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Renci.SshClient.Security +{ + internal class HMacMD5 : HMac + { + public override string Name + { + get { return "hmac-md5"; } + } + + public override void Init(IEnumerable key) + { + this._hmac = new System.Security.Cryptography.HMACMD5(key.Take(16).ToArray()); + } + } +} diff --git a/Renci.SshClient/Renci.SshClient/Security/HMacSha1.cs b/Renci.SshClient/Renci.SshClient/Security/HMacSha1.cs new file mode 100644 index 00000000..c049d55a --- /dev/null +++ b/Renci.SshClient/Renci.SshClient/Security/HMacSha1.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Security.Cryptography; + +namespace Renci.SshClient.Security +{ + internal class HMacSha1 : HMac + { + public override string Name + { + get { return "hmac-sha1"; } + } + + public override void Init(IEnumerable key) + { + this._hmac = new System.Security.Cryptography.HMACSHA1(key.Take(20).ToArray()); + } + } +} diff --git a/Renci.SshClient/Renci.SshClient/Security/KeyExchangeAlgorithm.cs b/Renci.SshClient/Renci.SshClient/Security/KeyExchangeAlgorithm.cs index a50aec5d..42805ea8 100644 --- a/Renci.SshClient/Renci.SshClient/Security/KeyExchangeAlgorithm.cs +++ b/Renci.SshClient/Renci.SshClient/Security/KeyExchangeAlgorithm.cs @@ -10,23 +10,23 @@ using Renci.SshClient.Messages.Transport; namespace Renci.SshClient.Security { - internal abstract class KeyExchangeAlgorithm : Algorithm + public abstract class KeyExchangeAlgorithm : Algorithm { public BigInteger SharedKey { get; protected set; } protected Session Session { get; set; } - private Func _clientCipher; + private string _clientCipherTypeName; - private Func _serverCipher; + private string _serverCipherTypeName; - private Func, HMAC> _cientHmacAlgorithm; + private string _cientHmacAlgorithmTypeName; - private Func, HMAC> _serverHmacAlgorithm; + private string _serverHmacAlgorithmTypeName; - private Func _compression; + private string _compressionTypeName; - private Func _decompression; + private string _decompressionTypeName; private IEnumerable _exchangeHash; /// @@ -72,21 +72,23 @@ namespace Renci.SshClient.Security public void Init(Session session, string clientEncryptionAlgorithmName, string serverDecryptionAlgorithmName, string clientHmacAlgorithmName, string serverHmacAlgorithmName, string compressionAlgorithmName, string decompressionAlgorithmName) { this.Session = session; - this._clientCipher = Settings.Encryptions[clientEncryptionAlgorithmName]; - this._serverCipher = Settings.Encryptions[clientEncryptionAlgorithmName]; - this._cientHmacAlgorithm = Settings.HmacAlgorithms[clientHmacAlgorithmName]; - this._serverHmacAlgorithm = Settings.HmacAlgorithms[serverHmacAlgorithmName]; - this._compression = Settings.CompressionAlgorithms[compressionAlgorithmName]; - this._decompression = Settings.CompressionAlgorithms[decompressionAlgorithmName]; + this._clientCipherTypeName = session.Encryptions[clientEncryptionAlgorithmName]; + this._serverCipherTypeName = session.Encryptions[clientEncryptionAlgorithmName]; + this._cientHmacAlgorithmTypeName = session.HmacAlgorithms[clientHmacAlgorithmName]; + this._serverHmacAlgorithmTypeName = session.HmacAlgorithms[serverHmacAlgorithmName]; + this._compressionTypeName = session.CompressionAlgorithms[compressionAlgorithmName]; + this._decompressionTypeName = session.CompressionAlgorithms[decompressionAlgorithmName]; session.MessageReceived += MessageHandler; session.KeyExchangeInitReceived += MessageHandler; session.NewKeysReceived += MessageHandler; } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Will be disposed by the session")] public Cipher CreateClientCipher() { - var clientCipher = this._clientCipher(); + // Create client cipher + var clientCipher = this._clientCipherTypeName.CreateInstance(); var exchangeHash = this.ExchangeHash; @@ -105,10 +107,11 @@ namespace Renci.SshClient.Security return clientCipher; } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Will be disposed by the session")] public Cipher CreateServerCipher() { - // Initilize server cipher - var serverCipher = this._serverCipher(); + // Create server cipher + var serverCipher = this._serverCipherTypeName.CreateInstance(); var exchangeHash = this.ExchangeHash; @@ -128,26 +131,52 @@ namespace Renci.SshClient.Security return serverCipher; } - public HMAC CreateClientMAC() + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Will be disposed by the session")] + public HMac CreateClientMAC() { var MACc2s = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'E', this.Session.SessionId)); - return this._cientHmacAlgorithm(MACc2s); + var mac = this._cientHmacAlgorithmTypeName.CreateInstance(); + + mac.Init(MACc2s); + + return mac; } - public HMAC CreateServerMAC() + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification="Will be disposed by the session")] + public HMac CreateServerMAC() { var MACs2c = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'F', this.Session.SessionId)); - return this._serverHmacAlgorithm(MACs2c); + var mac = this._serverHmacAlgorithmTypeName.CreateInstance(); + + mac.Init(MACs2c); + + return mac; } public Compressor CreateCompression() { - return this._compression(this.Session); + if (string.IsNullOrEmpty(this._compressionTypeName)) + { + return null; + } + var compressor = this._compressionTypeName.CreateInstance(); + + compressor.Init(this.Session); + + return compressor; } public Compressor CreateDecompression() { - return this._decompression(this.Session); + if (string.IsNullOrEmpty(this._decompressionTypeName)) + { + return null; + } + var compressor = this._decompressionTypeName.CreateInstance(); + + compressor.Init(this.Session); + + return compressor; } private void MessageHandler(object sender, MessageEventArgs e) diff --git a/Renci.SshClient/Renci.SshClient/Security/KeyExchangeDiffieHellman.cs b/Renci.SshClient/Renci.SshClient/Security/KeyExchangeDiffieHellman.cs index 67e03a43..fb9860b8 100644 --- a/Renci.SshClient/Renci.SshClient/Security/KeyExchangeDiffieHellman.cs +++ b/Renci.SshClient/Renci.SshClient/Security/KeyExchangeDiffieHellman.cs @@ -56,7 +56,7 @@ namespace Renci.SshClient.Security /// Initializes a new instance of the class. /// /// The session information. - internal KeyExchangeDiffieHellman() + public KeyExchangeDiffieHellman() : base() { } @@ -82,7 +82,7 @@ namespace Renci.SshClient.Security var data = bytes.Skip(4 + algorithmName.Length); - CryptoPublicKey key = Settings.HostKeyAlgorithms[algorithmName](); + CryptoPublicKey key = this.Session.HostKeyAlgorithms[algorithmName].CreateInstance(); key.Load(data); diff --git a/Renci.SshClient/Renci.SshClient/Security/UserAuthentication.cs b/Renci.SshClient/Renci.SshClient/Security/UserAuthentication.cs index 7ed5ac35..2a86d12b 100644 --- a/Renci.SshClient/Renci.SshClient/Security/UserAuthentication.cs +++ b/Renci.SshClient/Renci.SshClient/Security/UserAuthentication.cs @@ -13,7 +13,7 @@ namespace Renci.SshClient.Security protected Session Session { get; private set; } - public UserAuthentication(Session session) + public void Init(Session session) { this.Session = session; } diff --git a/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationHost.cs b/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationHost.cs index 2ead23ac..0dd29b2b 100644 --- a/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationHost.cs +++ b/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationHost.cs @@ -9,20 +9,10 @@ return "hostbased"; } } - public UserAuthenticationHost(Session session) - : base(session) - { - - } protected override bool Run() { throw new System.NotImplementedException(); } - - //protected override void HandleMessage(T message) - //{ - // throw new System.NotImplementedException(); - //} } } diff --git a/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationNone.cs b/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationNone.cs index 76df32fb..964cc3e8 100644 --- a/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationNone.cs +++ b/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationNone.cs @@ -14,12 +14,6 @@ namespace Renci.SshClient.Security get { return "none"; } } - public UserAuthenticationNone(Session session) - : base(session) - { - - } - protected override bool Run() { this.Session.SendMessage(new RequestMessage @@ -45,26 +39,9 @@ namespace Renci.SshClient.Security this._authenticationCompleted.Set(); } - - //protected override void HandleMessage(T message) - //{ - //} - - //protected override void HandleMessage(SuccessMessage message) - //{ - // base.HandleMessage(message); - // this._authenticationCompleted.Set(); - //} - - //protected override void HandleMessage(FailureMessage message) - //{ - // base.HandleMessage(message); - // this._authenticationCompleted.Set(); - //} - #region IDisposable Members - private bool disposed = false; + private bool _isDisposed = false; public void Dispose() { @@ -73,10 +50,10 @@ namespace Renci.SshClient.Security GC.SuppressFinalize(this); } - private void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. - if (!this.disposed) + if (!this._isDisposed) { // If disposing equals true, dispose all managed // and unmanaged resources. @@ -90,7 +67,7 @@ namespace Renci.SshClient.Security } // Note disposing has been done. - disposed = true; + _isDisposed = true; } } diff --git a/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationPassword.cs b/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationPassword.cs index cdb57cdd..8d4aa2a8 100644 --- a/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationPassword.cs +++ b/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationPassword.cs @@ -17,12 +17,6 @@ namespace Renci.SshClient.Security } } - public UserAuthenticationPassword(Session session) - : base(session) - { - - } - protected override bool Run() { // TODO: Handle all user authentication messages @@ -55,26 +49,9 @@ namespace Renci.SshClient.Security this._authenticationCompleted.Set(); } - //protected override void HandleMessage(T message) - //{ - // // TODO: Handle password specific messages - //} - - //protected override void HandleMessage(SuccessMessage message) - //{ - // base.HandleMessage(message); - // this._authenticationCompleted.Set(); - //} - - //protected override void HandleMessage(FailureMessage message) - //{ - // base.HandleMessage(message); - // this._authenticationCompleted.Set(); - //} - #region IDisposable Members - private bool disposed = false; + private bool isDisposed = false; public void Dispose() { @@ -83,10 +60,10 @@ namespace Renci.SshClient.Security GC.SuppressFinalize(this); } - private void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. - if (!this.disposed) + if (!this.isDisposed) { // If disposing equals true, dispose all managed // and unmanaged resources. @@ -100,7 +77,7 @@ namespace Renci.SshClient.Security } // Note disposing has been done. - disposed = true; + isDisposed = true; } } diff --git a/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationPublicKey.cs b/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationPublicKey.cs index 56ee1364..870e1e91 100644 --- a/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationPublicKey.cs +++ b/Renci.SshClient/Renci.SshClient/Security/UserAuthenticationPublicKey.cs @@ -18,12 +18,6 @@ namespace Renci.SshClient.Security } } - public UserAuthenticationPublicKey(Session session) - : base(session) - { - - } - protected override bool Run() { if (this.Session.ConnectionInfo.KeyFile == null) @@ -31,7 +25,7 @@ namespace Renci.SshClient.Security this.Session.RegisterMessageType(MessageTypes.UserAuthenticationInformationRequest); - // TODO: Complete full public key implemention which includes other messages + // TODO: Complete full public key implementation which includes other messages var message = new PublicKeyRequestMessage { ServiceName = ServiceNames.Connection, @@ -55,11 +49,6 @@ namespace Renci.SshClient.Security return true; } - //protected override void HandleMessage(T message) - //{ - // throw new System.NotImplementedException(); - //} - protected override void Session_UserAuthenticationSuccessMessageReceived(object sender, MessageEventArgs e) { base.Session_UserAuthenticationSuccessMessageReceived(sender, e); @@ -72,18 +61,6 @@ namespace Renci.SshClient.Security this._authenticationCompleted.Set(); } - //protected override void HandleMessage(SuccessMessage message) - //{ - // base.HandleMessage(message); - // this._authenticationCompleted.Set(); - //} - - //protected override void HandleMessage(FailureMessage message) - //{ - // base.HandleMessage(message); - // this._authenticationCompleted.Set(); - //} - private class SignatureData : SshData { @@ -117,7 +94,7 @@ namespace Renci.SshClient.Security #region IDisposable Members - private bool disposed = false; + private bool _isDisposed = false; public void Dispose() { @@ -126,10 +103,10 @@ namespace Renci.SshClient.Security GC.SuppressFinalize(this); } - private void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. - if (!this.disposed) + if (!this._isDisposed) { // If disposing equals true, dispose all managed // and unmanaged resources. @@ -143,7 +120,7 @@ namespace Renci.SshClient.Security } // Note disposing has been done. - disposed = true; + _isDisposed = true; } } diff --git a/Renci.SshClient/Renci.SshClient/Session.cs b/Renci.SshClient/Renci.SshClient/Session.cs index 6e681f6b..c577090d 100644 --- a/Renci.SshClient/Renci.SshClient/Session.cs +++ b/Renci.SshClient/Renci.SshClient/Session.cs @@ -88,17 +88,17 @@ namespace Renci.SshClient /// private bool _isDisconnecting; - public HMAC _serverMac; + private HMac _serverMac; - public HMAC _clientMac; + private HMac _clientMac; - public Cipher _clientCipher; + private Cipher _clientCipher; - public Cipher _serverCipher; + private Cipher _serverCipher; - public Compressor _serverDecompression; + private Compressor _serverDecompression; - public Compressor _clientCompression; + private Compressor _clientCompression; /// /// Hold session specific semaphores @@ -182,14 +182,14 @@ namespace Renci.SshClient { this._clientInitMessage = new KeyExchangeInitMessage() { - KeyExchangeAlgorithms = Settings.KeyExchangeAlgorithms.Keys, - ServerHostKeyAlgorithms = Settings.HostKeyAlgorithms.Keys, - EncryptionAlgorithmsClientToServer = Settings.Encryptions.Keys, - EncryptionAlgorithmsServerToClient = Settings.Encryptions.Keys, - MacAlgorithmsClientToSserver = Settings.HmacAlgorithms.Keys, - MacAlgorithmsServerToClient = Settings.HmacAlgorithms.Keys, - CompressionAlgorithmsClientToServer = Settings.CompressionAlgorithms.Keys, - CompressionAlgorithmsServerToClient = Settings.CompressionAlgorithms.Keys, + KeyExchangeAlgorithms = this.KeyExchangeAlgorithms.Keys, + ServerHostKeyAlgorithms = this.HostKeyAlgorithms.Keys, + EncryptionAlgorithmsClientToServer = this.Encryptions.Keys, + EncryptionAlgorithmsServerToClient = this.Encryptions.Keys, + MacAlgorithmsClientToSserver = this.HmacAlgorithms.Keys, + MacAlgorithmsServerToClient = this.HmacAlgorithms.Keys, + CompressionAlgorithmsClientToServer = this.CompressionAlgorithms.Keys, + CompressionAlgorithmsServerToClient = this.CompressionAlgorithms.Keys, LanguagesClientToServer = new string[] { string.Empty }, LanguagesServerToClient = new string[] { string.Empty }, FirstKexPacketFollows = false, @@ -367,6 +367,18 @@ namespace Renci.SshClient #endregion + public IDictionary KeyExchangeAlgorithms { get; private set; } + + public IDictionary Encryptions { get; private set; } + + public IDictionary HmacAlgorithms { get; private set; } + + public IDictionary HostKeyAlgorithms { get; private set; } + + public IDictionary SupportedAuthenticationMethods { get; private set; } + + public IDictionary CompressionAlgorithms { get; private set; } + /// /// Initializes a new instance of the class. /// @@ -375,6 +387,46 @@ namespace Renci.SshClient { this.ConnectionInfo = connectionInfo; this.ClientVersion = string.Format("SSH-2.0-Renci.SshClient.{0}", this.GetType().Assembly.GetName().Version); + + this.KeyExchangeAlgorithms = new Dictionary() + { + {"diffie-hellman-group1-sha1", typeof(KeyExchangeDiffieHellman).AssemblyQualifiedName}, + //"diffie-hellman-group-exchange-sha1" + }; + + this.Encryptions = new Dictionary() + { + {"3des-cbc", typeof(CipherTripleDES).AssemblyQualifiedName}, + {"aes128-cbc", typeof(CipherAES128CBC).AssemblyQualifiedName}, + {"aes192-cbc", typeof(CipherAES192CBC).AssemblyQualifiedName}, + {"aes256-cbc", typeof(CipherAES256CBC).AssemblyQualifiedName}, + }; + + this.HmacAlgorithms = new Dictionary() + { + {"hmac-md5", typeof(HMacMD5).AssemblyQualifiedName}, + {"hmac-sha1", typeof(HMacSha1).AssemblyQualifiedName}, + }; + + this.HostKeyAlgorithms = new Dictionary() + { + {"ssh-rsa", typeof(CryptoPublicKeyRsa).AssemblyQualifiedName}, + {"ssh-dsa", typeof(CryptoPublicKeyDss).AssemblyQualifiedName}, // TODO: Need to be tested + }; + + this.SupportedAuthenticationMethods = new Dictionary() + { + {"none", typeof(UserAuthenticationNone).AssemblyQualifiedName}, + {"publickey", typeof(UserAuthenticationPublicKey).AssemblyQualifiedName}, + {"password", typeof(UserAuthenticationPassword).AssemblyQualifiedName}, + }; + + this.CompressionAlgorithms = new Dictionary() + { + {"none", string.Empty}, + {"zlib", typeof(Zlib).AssemblyQualifiedName}, + {"zlib@openssh.com", typeof(ZlibOpenSsh).AssemblyQualifiedName}, + }; } /// @@ -418,7 +470,6 @@ namespace Renci.SshClient connectResult.AsyncWaitHandle.WaitOne(this.ConnectionInfo.Timeout); - this._socket.EndConnect(connectResult); this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1); @@ -464,7 +515,7 @@ namespace Renci.SshClient throw new SshConnectionException(string.Format("Server version '{0}' is not supported.", version), DisconnectReasons.ProtocolVersionNotSupported); } - this.Write(Encoding.ASCII.GetBytes(string.Format("{0}\n", this.ClientVersion))); + this.Write(Encoding.ASCII.GetBytes(string.Format("{0}\x0D\x0A", this.ClientVersion))); // Register Transport response messages this.RegisterMessageType(MessageTypes.Disconnect); @@ -498,11 +549,13 @@ namespace Renci.SshClient // Wait for service to be accepted this.WaitHandle(this._serviceAccepted); - // This implemention will ignore supported by server methods and will try to authenticated user using method supported by the client. + // This implementation will ignore supported by server methods and will try to authenticated user using method supported by the client. string errorMessage = null; // Hold last authentication error if any - foreach (var methodName in Settings.SupportedAuthenticationMethods.Keys) + foreach (var methodName in this.SupportedAuthenticationMethods.Keys) { - var userAuthentication = Settings.SupportedAuthenticationMethods[methodName](this); + var userAuthentication = this.SupportedAuthenticationMethods[methodName].CreateInstance(); + + userAuthentication.Init(this); if (userAuthentication.Execute()) { @@ -1024,20 +1077,20 @@ namespace Renci.SshClient this.SendMessage(this.ClientInitMessage); - var keyExchangeAlgorithm = (from c in Settings.KeyExchangeAlgorithms.Keys - from s in message.KeyExchangeAlgorithms - where s == c - select c).FirstOrDefault(); + var keyExchangeAlgorithmName = (from c in this.KeyExchangeAlgorithms.Keys + from s in message.KeyExchangeAlgorithms + where s == c + select c).FirstOrDefault(); - if (keyExchangeAlgorithm == null) + if (keyExchangeAlgorithmName == null) { throw new SshConnectionException("Failed to negotiate key exchange algorithm.", DisconnectReasons.KeyExchangeFailed); } - this._keyExchangeAlgorithm = Settings.KeyExchangeAlgorithms[keyExchangeAlgorithm](); + this._keyExchangeAlgorithm = this.KeyExchangeAlgorithms[keyExchangeAlgorithmName].CreateInstance(); // Determine encryption algorithm - var clientEncryptionAlgorithmName = (from b in Settings.Encryptions.Keys + var clientEncryptionAlgorithmName = (from b in this.Encryptions.Keys from a in message.EncryptionAlgorithmsClientToServer where a == b select a).FirstOrDefault(); @@ -1048,7 +1101,7 @@ namespace Renci.SshClient } // Determine encryption algorithm - var serverDecryptionAlgorithmName = (from b in Settings.Encryptions.Keys + var serverDecryptionAlgorithmName = (from b in this.Encryptions.Keys from a in message.EncryptionAlgorithmsServerToClient where a == b select a).FirstOrDefault(); @@ -1058,7 +1111,7 @@ namespace Renci.SshClient } // Determine client hmac algorithm - var clientHmacAlgorithmName = (from b in Settings.HmacAlgorithms.Keys + var clientHmacAlgorithmName = (from b in this.HmacAlgorithms.Keys from a in message.MacAlgorithmsClientToSserver where a == b select a).FirstOrDefault(); @@ -1068,7 +1121,7 @@ namespace Renci.SshClient } // Determine server hmac algorithm - var serverHmacAlgorithmName = (from b in Settings.HmacAlgorithms.Keys + var serverHmacAlgorithmName = (from b in this.HmacAlgorithms.Keys from a in message.MacAlgorithmsServerToClient where a == b select a).FirstOrDefault(); @@ -1078,7 +1131,7 @@ namespace Renci.SshClient } // Determine compression algorithm - var compressionAlgorithmName = (from b in Settings.CompressionAlgorithms.Keys + var compressionAlgorithmName = (from b in this.CompressionAlgorithms.Keys from a in message.CompressionAlgorithmsClientToServer where a == b select a).FirstOrDefault(); @@ -1088,7 +1141,7 @@ namespace Renci.SshClient } // Determine decompression algorithm - var decompressionAlgorithmName = (from b in Settings.CompressionAlgorithms.Keys + var decompressionAlgorithmName = (from b in this.CompressionAlgorithms.Keys from a in message.CompressionAlgorithmsServerToClient where a == b select a).FirstOrDefault(); @@ -1517,7 +1570,7 @@ namespace Renci.SshClient GC.SuppressFinalize(this); } - private void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. if (!this._disposed) @@ -1552,6 +1605,25 @@ namespace Renci.SshClient this._keyExchangeCompletedWaitHandle.Dispose(); } + if (this._clientCipher != null) + { + this._clientCipher.Dispose(); + } + + if (this._serverCipher != null) + { + this._serverCipher.Dispose(); + } + + if (this._clientMac != null) + { + this._clientMac.Dispose(); + } + + if (this._serverMac != null) + { + this._serverMac.Dispose(); + } } // Note disposing has been done. diff --git a/Renci.SshClient/Renci.SshClient/Settings.cs b/Renci.SshClient/Renci.SshClient/Settings.cs index d5888f7e..0073bae2 100644 --- a/Renci.SshClient/Renci.SshClient/Settings.cs +++ b/Renci.SshClient/Renci.SshClient/Settings.cs @@ -9,60 +9,60 @@ namespace Renci.SshClient { internal static class Settings { - public static IDictionary> KeyExchangeAlgorithms { get; private set; } + //public static IDictionary> KeyExchangeAlgorithms { get; private set; } - public static IDictionary> Encryptions { get; private set; } + //public static IDictionary> Encryptions { get; private set; } - public static IDictionary, HMAC>> HmacAlgorithms { get; private set; } + //public static IDictionary, HMAC>> HmacAlgorithms { get; private set; } - public static IDictionary> CompressionAlgorithms { get; private set; } + //public static IDictionary> CompressionAlgorithms { get; private set; } - public static IDictionary> HostKeyAlgorithms { get; private set; } + //public static IDictionary> HostKeyAlgorithms { get; private set; } - public static IDictionary> SupportedAuthenticationMethods { get; private set; } + //public static IDictionary> SupportedAuthenticationMethods { get; private set; } static Settings() { - Settings.KeyExchangeAlgorithms = new Dictionary>() - { - {"diffie-hellman-group1-sha1", () => { return new KeyExchangeDiffieHellman();}} - //"diffie-hellman-group-exchange-sha1" - }; + //Settings.KeyExchangeAlgorithms = new Dictionary>() + //{ + // {"diffie-hellman-group1-sha1", () => { return new KeyExchangeDiffieHellman();}} + // //"diffie-hellman-group-exchange-sha1" + //}; - Settings.Encryptions = new Dictionary>() - { - {"3des-cbc", () => { return new CipherTripleDES();}}, - {"aes128-cbc", () => { return new CipherAES128CBC();}}, - {"aes192-cbc", () => { return new CipherAES192CBC();}}, - {"aes256-cbc", () => { return new CipherAES256CBC();}}, - }; + //Settings.Encryptions = new Dictionary>() + //{ + // {"3des-cbc", () => { return new CipherTripleDES();}}, + // {"aes128-cbc", () => { return new CipherAES128CBC();}}, + // {"aes192-cbc", () => { return new CipherAES192CBC();}}, + // {"aes256-cbc", () => { return new CipherAES256CBC();}}, + //}; - Settings.HmacAlgorithms = new Dictionary, HMAC>>() - { - {"hmac-md5", (key) => { return new System.Security.Cryptography.HMACMD5(key.Take(16).ToArray());}}, - {"hmac-sha1", (key) => { return new System.Security.Cryptography.HMACSHA1(key.Take(20).ToArray());}}, - }; + //Settings.HmacAlgorithms = new Dictionary, HMAC>>() + //{ + // {"hmac-md5", (key) => { return new System.Security.Cryptography.HMACMD5(key.Take(16).ToArray());}}, + // {"hmac-sha1", (key) => { return new System.Security.Cryptography.HMACSHA1(key.Take(20).ToArray());}}, + //}; - Settings.HostKeyAlgorithms = new Dictionary>() - { - {"ssh-rsa", () => { return new CryptoPublicKeyRsa();}}, - {"ssh-dsa", () => { return new CryptoPublicKeyDss();}}, // TODO: Need to be tested - }; + //Settings.HostKeyAlgorithms = new Dictionary>() + //{ + // {"ssh-rsa", () => { return new CryptoPublicKeyRsa();}}, + // {"ssh-dsa", () => { return new CryptoPublicKeyDss();}}, // TODO: Need to be tested + //}; - Settings.SupportedAuthenticationMethods = new Dictionary>() - { - {"none", (session)=> {return new UserAuthenticationNone(session);}}, - {"publickey", (session)=> {return new UserAuthenticationPublicKey(session);}}, - {"password", (session)=> {return new UserAuthenticationPassword(session);}}, - }; + //Settings.SupportedAuthenticationMethods = new Dictionary>() + //{ + // {"none", (session)=> {return new UserAuthenticationNone(session);}}, + // {"publickey", (session)=> {return new UserAuthenticationPublicKey(session);}}, + // {"password", (session)=> {return new UserAuthenticationPassword(session);}}, + //}; - Settings.CompressionAlgorithms = new Dictionary>() - { - {"none", (session) => { return null;}}, - {"zlib", (session) => { return new Zlib(session);}}, - {"zlib@openssh.com", (session) => { return new ZlibOpenSsh(session);}}, - }; + //Settings.CompressionAlgorithms = new Dictionary>() + //{ + // {"none", (session) => { return null;}}, + // {"zlib", (session) => { return new Zlib(session);}}, + // {"zlib@openssh.com", (session) => { return new ZlibOpenSsh(session);}}, + //}; } } diff --git a/Renci.SshClient/Renci.SshClient/Sftp/SftpAsyncResult.cs b/Renci.SshClient/Renci.SshClient/Sftp/SftpAsyncResult.cs index 4f1a2834..c59ea6b4 100644 --- a/Renci.SshClient/Renci.SshClient/Sftp/SftpAsyncResult.cs +++ b/Renci.SshClient/Renci.SshClient/Sftp/SftpAsyncResult.cs @@ -71,7 +71,7 @@ namespace Renci.SshClient.Sftp GC.SuppressFinalize(this); } - private void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. if (!this._disposed) diff --git a/Renci.SshClient/Renci.SshClient/Sftp/SftpSession.cs b/Renci.SshClient/Renci.SshClient/Sftp/SftpSession.cs index fc1b7e53..14f4e40d 100644 --- a/Renci.SshClient/Renci.SshClient/Sftp/SftpSession.cs +++ b/Renci.SshClient/Renci.SshClient/Sftp/SftpSession.cs @@ -247,7 +247,7 @@ namespace Renci.SshClient.Sftp #region IDisposable Members - private bool disposed = false; + private bool _isDisposed = false; public void Dispose() { @@ -256,10 +256,10 @@ namespace Renci.SshClient.Sftp GC.SuppressFinalize(this); } - private void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. - if (!this.disposed) + if (!this._isDisposed) { // If disposing equals true, dispose all managed // and unmanaged resources. @@ -281,7 +281,7 @@ namespace Renci.SshClient.Sftp } // Note disposing has been done. - disposed = true; + _isDisposed = true; } } diff --git a/Renci.SshClient/Renci.SshClient/SshBaseClient.cs b/Renci.SshClient/Renci.SshClient/SshBaseClient.cs index dffeb56d..f383d0e2 100644 --- a/Renci.SshClient/Renci.SshClient/SshBaseClient.cs +++ b/Renci.SshClient/Renci.SshClient/SshBaseClient.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.IO; using Renci.SshClient.Sftp; +using Renci.SshClient.Security; namespace Renci.SshClient { @@ -118,7 +119,7 @@ namespace Renci.SshClient #region IDisposable Members - private bool disposed = false; + private bool _isDisposed = false; public void Dispose() { @@ -127,10 +128,10 @@ namespace Renci.SshClient GC.SuppressFinalize(this); } - private void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. - if (!this.disposed) + if (!this._isDisposed) { // If disposing equals true, dispose all managed // and unmanaged resources. @@ -144,7 +145,7 @@ namespace Renci.SshClient } // Note disposing has been done. - disposed = true; + _isDisposed = true; } } diff --git a/Renci.SshClient/Renci.SshClient/SshCommand.cs b/Renci.SshClient/Renci.SshClient/SshCommand.cs index 07d4fca5..372978df 100644 --- a/Renci.SshClient/Renci.SshClient/SshCommand.cs +++ b/Renci.SshClient/Renci.SshClient/SshCommand.cs @@ -288,7 +288,7 @@ namespace Renci.SshClient #region IDisposable Members - private bool disposed = false; + private bool _isDisposed = false; public void Dispose() { @@ -297,10 +297,10 @@ namespace Renci.SshClient GC.SuppressFinalize(this); } - private void Dispose(bool disposing) + protected virtual void Dispose(bool disposing) { // Check to see if Dispose has already been called. - if (!this.disposed) + if (!this._isDisposed) { // If disposing equals true, dispose all managed // and unmanaged resources. @@ -332,7 +332,7 @@ namespace Renci.SshClient } // Note disposing has been done. - disposed = true; + _isDisposed = true; } }