IDisposable interface refactoring

Remove Settings class and specify suported algorithm per session to allow in future to modify supported algorithms per connection
This commit is contained in:
olegkap_cp
2010-12-15 21:40:23 +00:00
parent 4caee0d629
commit ccda04e6f1
29 changed files with 423 additions and 293 deletions
@@ -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;
}
}
@@ -149,10 +149,5 @@ namespace Renci.SshClient.Channels
this._channelEof.Set();
}
protected override void OnDisposing()
{
}
}
}
@@ -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();
}
}
}
}
@@ -254,17 +254,6 @@ namespace Renci.SshClient.Channels
this._channelRequestResponse.Set();
}
/// <summary>
/// Called when object is being disposed.
/// </summary>
protected override void OnDisposing()
{
if (this._channelOpenResponseWaitHandle != null)
{
this._channelOpenResponseWaitHandle.Dispose();
}
}
/// <summary>
/// Sends the channel open message.
/// </summary>
@@ -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();
}
}
}
}
@@ -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<byte> bytes)
{
foreach (var b in bytes)
@@ -106,6 +106,16 @@ namespace Renci.SshClient
}
}
/// <summary>
/// Creates the instance of the type specified by the string.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="name">The name.</param>
/// <returns></returns>
internal static T CreateInstance<T>(this string name) where T : class
{
var type = Type.GetType(name);
return Activator.CreateInstance(type) as T;
}
}
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
}
@@ -84,6 +84,9 @@
<Compile Include="Messages\Connection\ChannelRequest\X11ForwardingRequestInfo.cs" />
<Compile Include="Messages\Connection\ChannelRequest\XonXoffRequestInfo.cs" />
<Compile Include="Messages\Sftp\SftpRequestMessage.cs" />
<Compile Include="Security\HMac.cs" />
<Compile Include="Security\HMacMD5.cs" />
<Compile Include="Security\HMacSha1.cs" />
<Compile Include="SftpClient.cs" />
<Compile Include="Sftp\CreateDirectoryCommand.cs" />
<Compile Include="Sftp\DownloadFileCommand.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<byte> Encrypt(IEnumerable<byte> data);
public abstract IEnumerable<byte> Decrypt(IEnumerable<byte> 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
}
}
@@ -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)
@@ -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
}
}
@@ -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<byte> 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
}
}
@@ -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<byte> key)
{
this._hmac = new System.Security.Cryptography.HMACMD5(key.Take(16).ToArray());
}
}
}
@@ -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<byte> key)
{
this._hmac = new System.Security.Cryptography.HMACSHA1(key.Take(20).ToArray());
}
}
}
@@ -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<Cipher> _clientCipher;
private string _clientCipherTypeName;
private Func<Cipher> _serverCipher;
private string _serverCipherTypeName;
private Func<IEnumerable<byte>, HMAC> _cientHmacAlgorithm;
private string _cientHmacAlgorithmTypeName;
private Func<IEnumerable<byte>, HMAC> _serverHmacAlgorithm;
private string _serverHmacAlgorithmTypeName;
private Func<Session, Compressor> _compression;
private string _compressionTypeName;
private Func<Session, Compressor> _decompression;
private string _decompressionTypeName;
private IEnumerable<byte> _exchangeHash;
/// <summary>
@@ -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<Cipher>();
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<Cipher>();
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<HMac>();
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<HMac>();
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>();
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>();
compressor.Init(this.Session);
return compressor;
}
private void MessageHandler(object sender, MessageEventArgs<Message> e)
@@ -56,7 +56,7 @@ namespace Renci.SshClient.Security
/// Initializes a new instance of the <see cref="KeyExchangeDiffieHellman"/> class.
/// </summary>
/// <param name="sessionInfo">The session information.</param>
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<CryptoPublicKey>();
key.Load(data);
@@ -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;
}
@@ -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>(T message)
//{
// throw new System.NotImplementedException();
//}
}
}
@@ -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>(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;
}
}
@@ -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>(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;
}
}
@@ -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<InformationRequestMessage>(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>(T message)
//{
// throw new System.NotImplementedException();
//}
protected override void Session_UserAuthenticationSuccessMessageReceived(object sender, MessageEventArgs<SuccessMessage> 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;
}
}
+104 -32
View File
@@ -88,17 +88,17 @@ namespace Renci.SshClient
/// </summary>
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;
/// <summary>
/// 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<string, string> KeyExchangeAlgorithms { get; private set; }
public IDictionary<string, string> Encryptions { get; private set; }
public IDictionary<string, string> HmacAlgorithms { get; private set; }
public IDictionary<string, string> HostKeyAlgorithms { get; private set; }
public IDictionary<string, string> SupportedAuthenticationMethods { get; private set; }
public IDictionary<string, string> CompressionAlgorithms { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="Session"/> class.
/// </summary>
@@ -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<string, string>()
{
{"diffie-hellman-group1-sha1", typeof(KeyExchangeDiffieHellman).AssemblyQualifiedName},
//"diffie-hellman-group-exchange-sha1"
};
this.Encryptions = new Dictionary<string, string>()
{
{"3des-cbc", typeof(CipherTripleDES).AssemblyQualifiedName},
{"aes128-cbc", typeof(CipherAES128CBC).AssemblyQualifiedName},
{"aes192-cbc", typeof(CipherAES192CBC).AssemblyQualifiedName},
{"aes256-cbc", typeof(CipherAES256CBC).AssemblyQualifiedName},
};
this.HmacAlgorithms = new Dictionary<string, string>()
{
{"hmac-md5", typeof(HMacMD5).AssemblyQualifiedName},
{"hmac-sha1", typeof(HMacSha1).AssemblyQualifiedName},
};
this.HostKeyAlgorithms = new Dictionary<string, string>()
{
{"ssh-rsa", typeof(CryptoPublicKeyRsa).AssemblyQualifiedName},
{"ssh-dsa", typeof(CryptoPublicKeyDss).AssemblyQualifiedName}, // TODO: Need to be tested
};
this.SupportedAuthenticationMethods = new Dictionary<string, string>()
{
{"none", typeof(UserAuthenticationNone).AssemblyQualifiedName},
{"publickey", typeof(UserAuthenticationPublicKey).AssemblyQualifiedName},
{"password", typeof(UserAuthenticationPassword).AssemblyQualifiedName},
};
this.CompressionAlgorithms = new Dictionary<string, string>()
{
{"none", string.Empty},
{"zlib", typeof(Zlib).AssemblyQualifiedName},
{"zlib@openssh.com", typeof(ZlibOpenSsh).AssemblyQualifiedName},
};
}
/// <summary>
@@ -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<DisconnectMessage>(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>();
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<KeyExchangeAlgorithm>();
// 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.
+40 -40
View File
@@ -9,60 +9,60 @@ namespace Renci.SshClient
{
internal static class Settings
{
public static IDictionary<string, Func<KeyExchangeAlgorithm>> KeyExchangeAlgorithms { get; private set; }
//public static IDictionary<string, Func<KeyExchangeAlgorithm>> KeyExchangeAlgorithms { get; private set; }
public static IDictionary<string, Func<Cipher>> Encryptions { get; private set; }
//public static IDictionary<string, Func<Cipher>> Encryptions { get; private set; }
public static IDictionary<string, Func<IEnumerable<byte>, HMAC>> HmacAlgorithms { get; private set; }
//public static IDictionary<string, Func<IEnumerable<byte>, HMAC>> HmacAlgorithms { get; private set; }
public static IDictionary<string, Func<Session, Compressor>> CompressionAlgorithms { get; private set; }
//public static IDictionary<string, Func<Session, Compressor>> CompressionAlgorithms { get; private set; }
public static IDictionary<string, Func<CryptoPublicKey>> HostKeyAlgorithms { get; private set; }
//public static IDictionary<string, Func<CryptoPublicKey>> HostKeyAlgorithms { get; private set; }
public static IDictionary<string, Func<Session, UserAuthentication>> SupportedAuthenticationMethods { get; private set; }
//public static IDictionary<string, Func<Session, UserAuthentication>> SupportedAuthenticationMethods { get; private set; }
static Settings()
{
Settings.KeyExchangeAlgorithms = new Dictionary<string, Func<KeyExchangeAlgorithm>>()
{
{"diffie-hellman-group1-sha1", () => { return new KeyExchangeDiffieHellman();}}
//"diffie-hellman-group-exchange-sha1"
};
//Settings.KeyExchangeAlgorithms = new Dictionary<string, Func<KeyExchangeAlgorithm>>()
//{
// {"diffie-hellman-group1-sha1", () => { return new KeyExchangeDiffieHellman();}}
// //"diffie-hellman-group-exchange-sha1"
//};
Settings.Encryptions = new Dictionary<string, Func<Cipher>>()
{
{"3des-cbc", () => { return new CipherTripleDES();}},
{"aes128-cbc", () => { return new CipherAES128CBC();}},
{"aes192-cbc", () => { return new CipherAES192CBC();}},
{"aes256-cbc", () => { return new CipherAES256CBC();}},
};
//Settings.Encryptions = new Dictionary<string, Func<Cipher>>()
//{
// {"3des-cbc", () => { return new CipherTripleDES();}},
// {"aes128-cbc", () => { return new CipherAES128CBC();}},
// {"aes192-cbc", () => { return new CipherAES192CBC();}},
// {"aes256-cbc", () => { return new CipherAES256CBC();}},
//};
Settings.HmacAlgorithms = new Dictionary<string, Func<IEnumerable<byte>, 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<string, Func<IEnumerable<byte>, 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<string, Func<CryptoPublicKey>>()
{
{"ssh-rsa", () => { return new CryptoPublicKeyRsa();}},
{"ssh-dsa", () => { return new CryptoPublicKeyDss();}}, // TODO: Need to be tested
};
//Settings.HostKeyAlgorithms = new Dictionary<string, Func<CryptoPublicKey>>()
//{
// {"ssh-rsa", () => { return new CryptoPublicKeyRsa();}},
// {"ssh-dsa", () => { return new CryptoPublicKeyDss();}}, // TODO: Need to be tested
//};
Settings.SupportedAuthenticationMethods = new Dictionary<string, Func<Session, UserAuthentication>>()
{
{"none", (session)=> {return new UserAuthenticationNone(session);}},
{"publickey", (session)=> {return new UserAuthenticationPublicKey(session);}},
{"password", (session)=> {return new UserAuthenticationPassword(session);}},
};
//Settings.SupportedAuthenticationMethods = new Dictionary<string, Func<Session, UserAuthentication>>()
//{
// {"none", (session)=> {return new UserAuthenticationNone(session);}},
// {"publickey", (session)=> {return new UserAuthenticationPublicKey(session);}},
// {"password", (session)=> {return new UserAuthenticationPassword(session);}},
//};
Settings.CompressionAlgorithms = new Dictionary<string, Func<Session, Compressor>>()
{
{"none", (session) => { return null;}},
{"zlib", (session) => { return new Zlib(session);}},
{"zlib@openssh.com", (session) => { return new ZlibOpenSsh(session);}},
};
//Settings.CompressionAlgorithms = new Dictionary<string, Func<Session, Compressor>>()
//{
// {"none", (session) => { return null;}},
// {"zlib", (session) => { return new Zlib(session);}},
// {"zlib@openssh.com", (session) => { return new ZlibOpenSsh(session);}},
//};
}
}
@@ -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)
@@ -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;
}
}
@@ -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;
}
}
@@ -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;
}
}