Files

987 lines
35 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using Renci.SshNet.Common;
using Renci.SshNet.Messages;
using Renci.SshNet.Messages.Authentication;
using Renci.SshNet.Messages.Connection;
using Renci.SshNet.Messages.Transport;
#if SILVERLIGHT
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
#else
using Microsoft.VisualStudio.TestTools.UnitTesting;
#endif
namespace Renci.SshNet.Tests
{
[TestClass]
public class SshMessageFactoryTest
{
private SshMessageFactory _sshMessageFactory;
private SshMessageFactoryOriginal _sshMessageFactoryOriginal;
[TestInitialize]
public void SetUp()
{
_sshMessageFactory = new SshMessageFactory();
_sshMessageFactoryOriginal = new SshMessageFactoryOriginal();
}
[TestMethod]
public void CreateShouldThrowSshExceptionWhenMessageIsNotEnabled()
{
const byte messageNumber = 60;
try
{
_sshMessageFactory.Create(messageNumber);
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
}
}
[TestMethod]
public void CreateShouldThrowSshExceptionWhenMessageDoesNotExist_OutsideOfMessageNumberRange()
{
const byte messageNumber = 255;
try
{
_sshMessageFactory.Create(messageNumber);
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not supported.", messageNumber), ex.Message);
}
}
[TestMethod]
public void CreateShouldThrowSshExceptionWhenMessageDoesNotExist_WithinMessageNumberRange()
{
const byte messageNumber = 5;
try
{
_sshMessageFactory.Create(messageNumber);
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not supported.", messageNumber), ex.Message);
}
}
[TestMethod]
public void CreateShouldThrowSshExceptionWhenMessageIsNotActivated()
{
const byte messageNumber = 60;
const string messageName = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ";
_sshMessageFactory.EnableAndActivateMessage(messageName);
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
try
{
_sshMessageFactory.Create(messageNumber);
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
}
}
[TestMethod]
public void CreateShouldReturnMessageInstanceCorrespondingToMessageNumberWhenMessageIsEnabledAndActivated()
{
const byte messageNumber = 60;
const string messageName = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ";
_sshMessageFactory.EnableAndActivateMessage(messageName);
var actual = _sshMessageFactory.Create(messageNumber);
Assert.IsNotNull(actual);
Assert.AreEqual(typeof (PasswordChangeRequiredMessage), actual.GetType());
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
actual = _sshMessageFactory.Create(messageNumber);
Assert.IsNotNull(actual);
Assert.AreEqual(typeof(InformationRequestMessage), actual.GetType());
}
[TestMethod]
public void DisableAndDeactivateMessageShouldThrowSshExceptionWhenAnotherMessageWithSameMessageNumberIsEnabled()
{
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
try
{
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual("Cannot enable message 'SSH_MSG_USERAUTH_INFO_REQUEST'. Message type 60 is already enabled for 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ'.", ex.Message);
}
// verify that the original message remains enabled
var actual = _sshMessageFactory.Create(60);
Assert.IsNotNull(actual);
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
}
[TestMethod]
public void DisableAndDeactivateMessageShouldNotThrowExceptionWhenMessageIsAlreadyDisabled()
{
const byte messageNumber = 60;
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
// verify that message remains disabled
try
{
_sshMessageFactory.Create(messageNumber);
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
}
}
[TestMethod]
public void DisableAndDeactivateMessageShouldNotThrowExceptionWhenMessageWasNeverEnabled()
{
const byte messageNumber = 60;
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
// verify that message is disabled
try
{
_sshMessageFactory.Create(messageNumber);
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
}
}
[TestMethod]
public void DisableAndDeactivateMessageShouldThrowSshExceptionWhenMessageIsNotSupported()
{
const string messageName = "WHATEVER";
try
{
_sshMessageFactory.DisableAndDeactivateMessage("WHATEVER");
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual(string.Format("Message '{0}' is not supported.", messageName), ex.Message);
}
}
[TestMethod]
public void DisableAndDeactivateMessageShouldThrowArgumentNullExceptionWhenMessageNameIsNull()
{
const string messageName = null;
try
{
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
Assert.Fail();
}
catch (ArgumentNullException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual("messageName", ex.ParamName);
}
}
[TestMethod]
public void EnableAndActivateMessageShouldThrowSshExceptionWhenAnotherMessageWithSameMessageNumberIsAlreadyEnabled()
{
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
try
{
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual("Cannot enable message 'SSH_MSG_USERAUTH_INFO_REQUEST'. Message type 60 is already enabled for 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ'.", ex.Message);
}
// verify that the original message remains enabled
var actual = _sshMessageFactory.Create(60);
Assert.IsNotNull(actual);
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
}
[TestMethod]
public void EnableAndActivateMessageShouldNotThrowExceptionWhenMessageIsAlreadyEnabled()
{
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
var actual = _sshMessageFactory.Create(60);
Assert.IsNotNull(actual);
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
}
[TestMethod]
public void EnableAndActivateMessageShouldThrowSshExceptionWhenMessageIsNotSupported()
{
const string messageName = "WHATEVER";
try
{
_sshMessageFactory.EnableAndActivateMessage("WHATEVER");
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual(string.Format("Message '{0}' is not supported.", messageName), ex.Message);
}
}
[TestMethod]
public void EnableAndActivateMessageShouldThrowArgumentNullExceptionWhenMessageNameIsNull()
{
const string messageName = null;
try
{
_sshMessageFactory.EnableAndActivateMessage(messageName);
Assert.Fail();
}
catch (ArgumentNullException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual("messageName", ex.ParamName);
}
}
[TestMethod]
public void DisableNonKeyExchangeMessagesShouldDisableNonKeyExchangeMessages()
{
const byte messageNumber = 60;
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
_sshMessageFactory.DisableNonKeyExchangeMessages();
// verify that message is disabled
try
{
_sshMessageFactory.Create(messageNumber);
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
}
}
[TestMethod]
public void DisableNonKeyExchangeMessagesShouldNotDisableKeyExchangeMessages()
{
const byte messageNumber = 21;
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_NEWKEYS");
_sshMessageFactory.DisableNonKeyExchangeMessages();
// verify that message remains enabled
var actual = _sshMessageFactory.Create(messageNumber);
Assert.IsNotNull(actual);
Assert.AreEqual(typeof (NewKeysMessage), actual.GetType());
}
[TestMethod]
public void EnableActivatedMessagesShouldEnableMessagesThatWereEnabledPriorToInvokingDisableNonKeyExchangeMessages()
{
const byte messageNumber = 60;
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
_sshMessageFactory.DisableNonKeyExchangeMessages();
_sshMessageFactory.EnableActivatedMessages();
var actual = _sshMessageFactory.Create(messageNumber);
Assert.IsNotNull(actual);
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
}
[TestMethod]
public void EnableActivatedMessagesShouldNotEnableMessagesThatWereDisabledPriorToInvokingDisableNonKeyExchangeMessages()
{
const byte messageNumber = 60;
_sshMessageFactory.DisableNonKeyExchangeMessages();
_sshMessageFactory.EnableActivatedMessages();
try
{
_sshMessageFactory.Create(messageNumber);
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
}
}
[TestMethod]
public void EnableActivatedMessagesShouldNotEnableMessagesThatWereDisabledAfterInvokingDisableNonKeyExchangeMessages()
{
const byte messageNumber = 60;
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
_sshMessageFactory.DisableNonKeyExchangeMessages();
_sshMessageFactory.DisableAndDeactivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
_sshMessageFactory.EnableActivatedMessages();
try
{
_sshMessageFactory.Create(messageNumber);
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid in the current context.", messageNumber), ex.Message);
}
}
[TestMethod]
public void EnableActivatedMessagesShouldThrowSshExceptionWhenAnothersMessageWithSameMessageNumberWasEnabledAfterInvokingDisableNonKeyExchangeMessages()
{
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
_sshMessageFactory.DisableNonKeyExchangeMessages();
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
try
{
_sshMessageFactory.EnableActivatedMessages();
Assert.Fail();
}
catch (SshException ex)
{
Assert.IsNull(ex.InnerException);
Assert.AreEqual("Cannot enable message 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ'. Message type 60 is already enabled for 'SSH_MSG_USERAUTH_INFO_REQUEST'.", ex.Message);
}
}
[TestMethod]
public void EnableActivatedMessagesShouldLeaveMessagesEnabledThatWereEnabledAfterInvokingDisableNonKeyExchangeMessages()
{
const byte messageNumber = 60;
_sshMessageFactory.DisableNonKeyExchangeMessages();
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
_sshMessageFactory.EnableActivatedMessages();
var actual = _sshMessageFactory.Create(messageNumber);
Assert.IsNotNull(actual);
Assert.AreEqual(typeof(PasswordChangeRequiredMessage), actual.GetType());
}
[TestMethod]
public void HighestMessageNumberShouldCorrespondWithHighestSupportedMessageNumber()
{
var highestSupportMessageNumber = SshMessageFactory.AllMessages.Max(m => m.Number);
Assert.AreEqual(highestSupportMessageNumber, SshMessageFactory.HighestMessageNumber);
}
[TestMethod]
public void TotalMessageCountShouldBeTotalNumberOfSupportedMessages()
{
var totalNumberOfSupportedMessages = SshMessageFactory.AllMessages.Length;
Assert.AreEqual(totalNumberOfSupportedMessages, SshMessageFactory.TotalMessageCount);
}
[TestMethod]
[TestCategory("Performance")]
public void Performance_Ctor()
{
const int runCount = 100000;
// warm-up
for (var i = 0; i < 3; i++)
{
var sshMessageFactory = new SshMessageFactory();
var sshMessageFactoryOriginal = new SshMessageFactoryOriginal();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
var stopwatch = new Stopwatch();
stopwatch.Start();
for (var i = 0; i < runCount; i++)
{
var sshMessageFactory = new SshMessageFactory();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
stopwatch.Reset();
stopwatch.Start();
for (var i = 0; i < runCount; i++)
{
var sshMessageFactory = new SshMessageFactoryOriginal();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
[TestMethod]
[TestCategory("LongRunning")]
[TestCategory("Performance")]
public void Performance_Create()
{
const int runCount = 10000000;
const string messageName = "SSH_MSG_CHANNEL_CLOSE";
_sshMessageFactory.EnableAndActivateMessage(messageName);
_sshMessageFactoryOriginal.EnableAndActivateMessage(messageName);
// warm-up
for (var i = 0; i < 3; i++)
{
_sshMessageFactory.Create(97);
_sshMessageFactoryOriginal.Create(97);
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
var stopwatch = new Stopwatch();
stopwatch.Start();
for (var i = 0; i < runCount; i++)
{
var msg = _sshMessageFactory.Create(97);
if (msg == null)
Console.WriteLine();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
stopwatch.Reset();
stopwatch.Start();
for (var i = 0; i < runCount; i++)
{
var msg = _sshMessageFactoryOriginal.Create(97);
if (msg == null)
Console.WriteLine();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
[TestMethod]
[TestCategory("LongRunning")]
[TestCategory("Performance")]
public void Performance_EnableAndActivateMessage()
{
const int runCount = 1000000;
const string messageName = "SSH_MSG_CHANNEL_CLOSE";
// warm-up
for (var i = 0; i < 3; i++)
{
_sshMessageFactory.EnableAndActivateMessage(messageName);
_sshMessageFactoryOriginal.EnableAndActivateMessage(messageName);
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
var stopwatch = new Stopwatch();
stopwatch.Start();
for (var i = 0; i < runCount; i++)
_sshMessageFactory.EnableAndActivateMessage(messageName);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
stopwatch.Reset();
stopwatch.Start();
for (var i = 0; i < runCount; i++)
_sshMessageFactoryOriginal.EnableAndActivateMessage(messageName);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
[TestMethod]
[TestCategory("LongRunning")]
[TestCategory("Performance")]
public void Performance_DisableAndDeactivateMessage()
{
const int runCount = 1000000;
const string messageName = "SSH_MSG_CHANNEL_CLOSE";
// warm-up
for (var i = 0; i < 3; i++)
{
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
_sshMessageFactoryOriginal.DisableAndDeactivateMessage(messageName);
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
var stopwatch = new Stopwatch();
stopwatch.Start();
for (var i = 0; i < runCount; i++)
_sshMessageFactory.DisableAndDeactivateMessage(messageName);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
stopwatch.Reset();
stopwatch.Start();
for (var i = 0; i < runCount; i++)
_sshMessageFactoryOriginal.DisableAndDeactivateMessage(messageName);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
[TestMethod]
[TestCategory("LongRunning")]
[TestCategory("Performance")]
public void Performance_DisableNonKeyExchangeMessages()
{
const int runCount = 1000000;
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_USERAUTH_BANNER");
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_DEBUG");
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_UNIMPLEMENTED");
_sshMessageFactory.EnableAndActivateMessage("SSH_MSG_SERVICE_ACCEPT");
_sshMessageFactoryOriginal.EnableAndActivateMessage("SSH_MSG_USERAUTH_BANNER");
_sshMessageFactoryOriginal.EnableAndActivateMessage("SSH_MSG_DEBUG");
_sshMessageFactoryOriginal.EnableAndActivateMessage("SSH_MSG_UNIMPLEMENTED");
_sshMessageFactoryOriginal.EnableAndActivateMessage("SSH_MSG_SERVICE_ACCEPT");
// warm-up
for (var i = 0; i < 3; i++)
{
_sshMessageFactory.DisableNonKeyExchangeMessages();
_sshMessageFactory.EnableActivatedMessages();
_sshMessageFactoryOriginal.DisableNonKeyExchangeMessages();
_sshMessageFactoryOriginal.EnableActivatedMessages();
}
//Console.WriteLine("Starting test");
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
var stopwatch = new Stopwatch();
stopwatch.Start();
for (var i = 0; i < runCount; i++)
{
_sshMessageFactory.DisableNonKeyExchangeMessages();
_sshMessageFactory.EnableActivatedMessages();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
stopwatch.Reset();
stopwatch.Start();
for (var i = 0; i < runCount; i++)
{
_sshMessageFactoryOriginal.DisableNonKeyExchangeMessages();
_sshMessageFactoryOriginal.EnableActivatedMessages();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
}
internal class SshMessageFactoryOriginal
{
private readonly IEnumerable<MessageMetadata> _messagesMetadata;
public SshMessageFactoryOriginal()
{
_messagesMetadata = new[]
{
new MessageMetadata {Name = "SSH_MSG_NEWKEYS", Number = 21, Type = typeof(NewKeysMessage)},
new MessageMetadata
{
Name = "SSH_MSG_REQUEST_FAILURE",
Number = 82,
Type = typeof(RequestFailureMessage)
},
new MessageMetadata {Name = "SSH_MSG_KEXINIT", Number = 20, Type = typeof(KeyExchangeInitMessage)},
new MessageMetadata
{
Name = "SSH_MSG_CHANNEL_OPEN_FAILURE",
Number = 92,
Type = typeof(ChannelOpenFailureMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_CHANNEL_FAILURE",
Number = 100,
Type = typeof(ChannelFailureMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_CHANNEL_EXTENDED_DATA",
Number = 95,
Type = typeof(ChannelExtendedDataMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_CHANNEL_DATA",
Number = 94,
Type = typeof(ChannelDataMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_USERAUTH_REQUEST",
Number = 50,
Type = typeof(RequestMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_CHANNEL_REQUEST",
Number = 98,
Type = typeof(ChannelRequestMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_USERAUTH_BANNER",
Number = 53,
Type = typeof(BannerMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_USERAUTH_INFO_RESPONSE",
Number = 61,
Type = typeof(InformationResponseMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_USERAUTH_FAILURE",
Number = 51,
Type = typeof(FailureMessage)
},
new MessageMetadata {Name = "SSH_MSG_DEBUG", Number = 4, Type = typeof(DebugMessage),},
new MessageMetadata
{
Name = "SSH_MSG_KEXDH_INIT",
Number = 30,
Type = typeof(KeyExchangeDhInitMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_GLOBAL_REQUEST",
Number = 80,
Type = typeof(GlobalRequestMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_CHANNEL_OPEN",
Number = 90,
Type = typeof(ChannelOpenMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_CHANNEL_OPEN_CONFIRMATION",
Number = 91,
Type = typeof(ChannelOpenConfirmationMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_USERAUTH_INFO_REQUEST",
Number = 60,
Type = typeof(InformationRequestMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_UNIMPLEMENTED",
Number = 3,
Type = typeof(UnimplementedMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_REQUEST_SUCCESS",
Number = 81,
Type = typeof(RequestSuccessMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_CHANNEL_SUCCESS",
Number = 99,
Type = typeof(ChannelSuccessMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ",
Number = 60,
Type = typeof(PasswordChangeRequiredMessage)
},
new MessageMetadata {Name = "SSH_MSG_DISCONNECT", Number = 1, Type = typeof(DisconnectMessage)},
new MessageMetadata
{
Name = "SSH_MSG_SERVICE_REQUEST",
Number = 5,
Type = typeof(ServiceRequestMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_KEX_DH_GEX_REQUEST",
Number = 34,
Type = typeof(KeyExchangeDhGroupExchangeRequest)
},
new MessageMetadata
{
Name = "SSH_MSG_KEX_DH_GEX_GROUP",
Number = 31,
Type = typeof(KeyExchangeDhGroupExchangeGroup)
},
new MessageMetadata
{
Name = "SSH_MSG_USERAUTH_SUCCESS",
Number = 52,
Type = typeof(SuccessMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_USERAUTH_PK_OK",
Number = 60,
Type = typeof(PublicKeyMessage)
},
new MessageMetadata {Name = "SSH_MSG_IGNORE", Number = 2, Type = typeof(IgnoreMessage)},
new MessageMetadata
{
Name = "SSH_MSG_CHANNEL_WINDOW_ADJUST",
Number = 93,
Type = typeof(ChannelWindowAdjustMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_CHANNEL_EOF",
Number = 96,
Type = typeof(ChannelEofMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_CHANNEL_CLOSE",
Number = 97,
Type = typeof(ChannelCloseMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_SERVICE_ACCEPT",
Number = 6,
Type = typeof(ServiceAcceptMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_KEXDH_REPLY",
Number = 31,
Type = typeof(KeyExchangeDhReplyMessage)
},
new MessageMetadata
{
Name = "SSH_MSG_KEX_DH_GEX_INIT",
Number = 32,
Type = typeof(KeyExchangeDhGroupExchangeInit)
},
new MessageMetadata
{
Name = "SSH_MSG_KEX_DH_GEX_REPLY",
Number = 33,
Type = typeof(KeyExchangeDhGroupExchangeReply)
}
};
}
/// <summary>
/// Disables and deactivate all messages.
/// </summary>
public void Reset()
{
foreach (var messageMetadata in _messagesMetadata)
{
messageMetadata.Activated = messageMetadata.Enabled = false;
}
}
public void EnableActivatedMessages()
{
foreach (var messageMetadata in _messagesMetadata)
{
if (messageMetadata.Activated)
messageMetadata.Enabled = true;
}
}
public Message Create(byte messageNumber)
{
var messageMetadata =
(from m in _messagesMetadata where m.Number == messageNumber && m.Enabled && m.Activated select m)
.FirstOrDefault();
if (messageMetadata == null)
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid.",
messageNumber));
return messageMetadata.Type.CreateInstance<Message>();
}
public void DisableNonKeyExchangeMessages()
{
foreach (var messageMetadata in _messagesMetadata)
{
if (messageMetadata.Activated && messageMetadata.Number > 2 &&
(messageMetadata.Number < 20 || messageMetadata.Number > 30))
{
//Console.WriteLine("Disabling " + messageMetadata.Name + "...");
messageMetadata.Enabled = false;
}
}
}
public void EnableAndActivateMessage(string messageName)
{
lock (_messagesMetadata)
{
var messagesMetadata = _messagesMetadata.Where(m => m.Name == messageName);
foreach (var messageMetadata in messagesMetadata)
messageMetadata.Enabled = messageMetadata.Activated = true;
}
}
public void DisableAndDeactivateMessage(string messageName)
{
lock (_messagesMetadata)
{
var messagesMetadata = _messagesMetadata.Where(m => m.Name == messageName);
foreach (var messageMetadata in messagesMetadata)
messageMetadata.Enabled = messageMetadata.Activated = false;
}
}
private class MessageMetadata
{
public string Name { get; set; }
public byte Number { get; set; }
public bool Enabled { get; set; }
public bool Activated { get; set; }
public Type Type { get; set; }
}
}
}
}