diff --git a/src/Renci.SshNet/Abstractions/DiagnosticAbstraction.cs b/src/Renci.SshNet/Abstractions/DiagnosticAbstraction.cs
index 014d70689..9de9bbea4 100644
--- a/src/Renci.SshNet/Abstractions/DiagnosticAbstraction.cs
+++ b/src/Renci.SshNet/Abstractions/DiagnosticAbstraction.cs
@@ -1,27 +1,65 @@
-using System.Diagnostics;
+using System.ComponentModel;
+using System.Diagnostics;
namespace Renci.SshNet.Abstractions
{
- internal static class DiagnosticAbstraction
+ ///
+ /// Provides access to the internals of SSH.NET.
+ ///
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static class DiagnosticAbstraction
{
- private static readonly SourceSwitch SourceSwitch = new SourceSwitch("SshNetSwitch");
-
- public static bool IsEnabled(TraceEventType traceEventType)
- {
- return SourceSwitch.ShouldTrace(traceEventType);
- }
-
- private static readonly TraceSource Loggging =
#if DEBUG
- new TraceSource("SshNet.Logging", SourceLevels.All);
-#else
- new TraceSource("SshNet.Logging");
-#endif // DEBUG
+ ///
+ /// The instance used by SSH.NET.
+ ///
+ ///
+ ///
+ /// Configuration on .NET Core must be done programmatically, e.g.
+ ///
+ /// DiagnosticAbstraction.Source.Switch = new SourceSwitch("sourceSwitch", "Verbose");
+ /// DiagnosticAbstraction.Source.Listeners.Remove("Default");
+ /// DiagnosticAbstraction.Source.Listeners.Add(new ConsoleTraceListener());
+ /// DiagnosticAbstraction.Source.Listeners.Add(new TextWriterTraceListener("trace.log"));
+ ///
+ ///
+ ///
+ /// On .NET Framework, it is possible to configure via App.config, e.g.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// ]]>
+ ///
+ ///
+ ///
+ public static readonly TraceSource Source = new TraceSource("SshNet.Logging");
+#endif
+ ///
+ /// Logs a message to at the
+ /// level.
+ ///
+ /// The message to log.
[Conditional("DEBUG")]
public static void Log(string text)
{
- Loggging.TraceEvent(TraceEventType.Verbose,
+ Source.TraceEvent(TraceEventType.Verbose,
System.Environment.CurrentManagedThreadId,
text);
}
diff --git a/src/Renci.SshNet/Messages/Authentication/FailureMessage.cs b/src/Renci.SshNet/Messages/Authentication/FailureMessage.cs
index 61379600f..f02705ecb 100644
--- a/src/Renci.SshNet/Messages/Authentication/FailureMessage.cs
+++ b/src/Renci.SshNet/Messages/Authentication/FailureMessage.cs
@@ -60,5 +60,13 @@ internal override void Process(Session session)
{
session.OnUserAuthenticationFailureReceived(this);
}
+
+ ///
+ public override string ToString()
+ {
+#pragma warning disable MA0089 // Optimize string method usage
+ return $"SSH_MSG_USERAUTH_FAILURE {string.Join(",", AllowedAuthentications)} ({nameof(PartialSuccess)}:{PartialSuccess})";
+#pragma warning restore MA0089 // Optimize string method usage
+ }
}
}
diff --git a/src/Renci.SshNet/Messages/Authentication/PublicKeyMessage.cs b/src/Renci.SshNet/Messages/Authentication/PublicKeyMessage.cs
index b5582b788..b917ab99a 100644
--- a/src/Renci.SshNet/Messages/Authentication/PublicKeyMessage.cs
+++ b/src/Renci.SshNet/Messages/Authentication/PublicKeyMessage.cs
@@ -60,5 +60,11 @@ protected override void SaveData()
WriteBinaryString(PublicKeyAlgorithmName);
WriteBinaryString(PublicKeyData);
}
+
+ ///
+ public override string ToString()
+ {
+ return $"SSH_MSG_USERAUTH_PK_OK ({Ascii.GetString(PublicKeyAlgorithmName)})";
+ }
}
}
diff --git a/src/Renci.SshNet/Messages/Authentication/RequestMessage.cs b/src/Renci.SshNet/Messages/Authentication/RequestMessage.cs
index 5393df3f7..57f60849f 100644
--- a/src/Renci.SshNet/Messages/Authentication/RequestMessage.cs
+++ b/src/Renci.SshNet/Messages/Authentication/RequestMessage.cs
@@ -106,5 +106,11 @@ internal override void Process(Session session)
{
throw new NotImplementedException();
}
+
+ ///
+ public override string ToString()
+ {
+ return $"SSH_MSG_USERAUTH_REQUEST ({MethodName})";
+ }
}
}
diff --git a/src/Renci.SshNet/Messages/Authentication/RequestMessagePublicKey.cs b/src/Renci.SshNet/Messages/Authentication/RequestMessagePublicKey.cs
index 391e60e76..a759ef20c 100644
--- a/src/Renci.SshNet/Messages/Authentication/RequestMessagePublicKey.cs
+++ b/src/Renci.SshNet/Messages/Authentication/RequestMessagePublicKey.cs
@@ -96,5 +96,11 @@ protected override void SaveData()
WriteBinaryString(Signature);
}
}
+
+ ///
+ public override string ToString()
+ {
+ return $"{base.ToString()} {Ascii.GetString(PublicKeyAlgorithmName)} {(Signature != null ? "with" : "without")} signature.";
+ }
}
}
diff --git a/src/Renci.SshNet/Renci.SshNet.csproj b/src/Renci.SshNet/Renci.SshNet.csproj
index 4ccf6c72e..89e82349d 100644
--- a/src/Renci.SshNet/Renci.SshNet.csproj
+++ b/src/Renci.SshNet/Renci.SshNet.csproj
@@ -6,7 +6,7 @@
- FEATURE_BINARY_SERIALIZATION;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_DNS_SYNC;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_RIPEMD160
+ $(DefineConstants);FEATURE_BINARY_SERIALIZATION;FEATURE_SOCKET_EAP;FEATURE_SOCKET_APM;FEATURE_DNS_SYNC;FEATURE_HASH_RIPEMD160_CREATE;FEATURE_HMAC_RIPEMD160
@@ -18,6 +18,6 @@
- FEATURE_SOCKET_TAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_EAP;FEATURE_DNS_SYNC;FEATURE_DNS_APM;FEATURE_DNS_TAP
+ $(DefineConstants);FEATURE_SOCKET_TAP;FEATURE_SOCKET_APM;FEATURE_SOCKET_EAP;FEATURE_DNS_SYNC;FEATURE_DNS_APM;FEATURE_DNS_TAP
diff --git a/src/Renci.SshNet/Security/KeyExchange.cs b/src/Renci.SshNet/Security/KeyExchange.cs
index 5024941bf..44684a92e 100644
--- a/src/Renci.SshNet/Security/KeyExchange.cs
+++ b/src/Renci.SshNet/Security/KeyExchange.cs
@@ -183,11 +183,9 @@ public Cipher CreateServerCipher()
serverKey = GenerateSessionKey(SharedKey, ExchangeHash, serverKey, _serverCipherInfo.KeySize / 8);
- DiagnosticAbstraction.Log(string.Format("[{0}] Creating server cipher (Name:{1},Key:{2},IV:{3})",
+ DiagnosticAbstraction.Log(string.Format("[{0}] Creating {1} server cipher.",
Session.ToHex(Session.SessionId),
- Session.ConnectionInfo.CurrentServerEncryption,
- Session.ToHex(serverKey),
- Session.ToHex(serverVector)));
+ Session.ConnectionInfo.CurrentServerEncryption));
// Create server cipher
return _serverCipherInfo.Cipher(serverKey, serverVector);
@@ -210,6 +208,10 @@ public Cipher CreateClientCipher()
clientKey = GenerateSessionKey(SharedKey, ExchangeHash, clientKey, _clientCipherInfo.KeySize / 8);
+ DiagnosticAbstraction.Log(string.Format("[{0}] Creating {1} client cipher.",
+ Session.ToHex(Session.SessionId),
+ Session.ConnectionInfo.CurrentClientEncryption));
+
// Create client cipher
return _clientCipherInfo.Cipher(clientKey, clientVector);
}
@@ -230,6 +232,10 @@ public HashAlgorithm CreateServerHash()
Hash(GenerateSessionKey(SharedKey, ExchangeHash, 'F', sessionId)),
_serverHashInfo.KeySize / 8);
+ DiagnosticAbstraction.Log(string.Format("[{0}] Creating {1} server hmac algorithm.",
+ Session.ToHex(Session.SessionId),
+ Session.ConnectionInfo.CurrentServerHmacAlgorithm));
+
return _serverHashInfo.HashAlgorithm(serverKey);
}
@@ -249,6 +255,10 @@ public HashAlgorithm CreateClientHash()
Hash(GenerateSessionKey(SharedKey, ExchangeHash, 'E', sessionId)),
_clientHashInfo.KeySize / 8);
+ DiagnosticAbstraction.Log(string.Format("[{0}] Creating {1} client hmac algorithm.",
+ Session.ToHex(Session.SessionId),
+ Session.ConnectionInfo.CurrentClientHmacAlgorithm));
+
return _clientHashInfo.HashAlgorithm(clientKey);
}
@@ -265,6 +275,10 @@ public Compressor CreateCompressor()
return null;
}
+ DiagnosticAbstraction.Log(string.Format("[{0}] Creating {1} client compressor.",
+ Session.ToHex(Session.SessionId),
+ Session.ConnectionInfo.CurrentClientCompressionAlgorithm));
+
var compressor = _compressionType.CreateInstance();
compressor.Init(Session);
@@ -285,6 +299,10 @@ public Compressor CreateDecompressor()
return null;
}
+ DiagnosticAbstraction.Log(string.Format("[{0}] Creating {1} server decompressor.",
+ Session.ToHex(Session.SessionId),
+ Session.ConnectionInfo.CurrentServerCompressionAlgorithm));
+
var decompressor = _decompressionType.CreateInstance();
decompressor.Init(Session);
diff --git a/src/Renci.SshNet/Session.cs b/src/Renci.SshNet/Session.cs
index 2d913d072..f05c0e0a0 100644
--- a/src/Renci.SshNet/Session.cs
+++ b/src/Renci.SshNet/Session.cs
@@ -616,7 +616,7 @@ public void Connect()
ServerVersion = ConnectionInfo.ServerVersion = serverIdentification.ToString();
ConnectionInfo.ClientVersion = ClientVersion;
- DiagnosticAbstraction.Log(string.Format("Server version '{0}' on '{1}'.", serverIdentification.ProtocolVersion, serverIdentification.SoftwareVersion));
+ DiagnosticAbstraction.Log(string.Format("Server version '{0}'.", serverIdentification));
if (!(serverIdentification.ProtocolVersion.Equals("2.0") || serverIdentification.ProtocolVersion.Equals("1.99")))
{
@@ -728,7 +728,7 @@ public async Task ConnectAsync(CancellationToken cancellationToken)
ServerVersion = ConnectionInfo.ServerVersion = serverIdentification.ToString();
ConnectionInfo.ClientVersion = ClientVersion;
- DiagnosticAbstraction.Log(string.Format("Server version '{0}' on '{1}'.", serverIdentification.ProtocolVersion, serverIdentification.SoftwareVersion));
+ DiagnosticAbstraction.Log(string.Format("Server version '{0}'.", serverIdentification));
if (!(serverIdentification.ProtocolVersion.Equals("2.0") || serverIdentification.ProtocolVersion.Equals("1.99")))
{
@@ -1397,6 +1397,8 @@ internal void OnKeyExchangeInitReceived(KeyExchangeInitMessage message)
ConnectionInfo.CurrentKeyExchangeAlgorithm = _keyExchange.Name;
+ DiagnosticAbstraction.Log(string.Format("[{0}] Performing {1} key exchange.", ToHex(SessionId), ConnectionInfo.CurrentKeyExchangeAlgorithm));
+
_keyExchange.HostKeyReceived += KeyExchange_HostKeyReceived;
// Start the algorithm implementation