Skip to content

Commit

Permalink
Allow custom definition of SSL encryption protocols for the connection
Browse files Browse the repository at this point in the history
Add property to define encryption protocols. This allows use of TLS 1.1
and TLS 1.2 protocols, which are disabled by default.
  • Loading branch information
hurcane committed Aug 21, 2015
1 parent 50492b5 commit 4f72ff7
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 12 deletions.
1 change: 1 addition & 0 deletions Examples/Examples.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
<Compile Include="OpenWrite.cs" />
<Compile Include="OpenWriteURI.cs" />
<Compile Include="Rename.cs" />
<Compile Include="SetEncryptionProtocols.cs" />
<Compile Include="SetHashAlgorithm.cs" />
<Compile Include="SetWorkingDirectory.cs" />
<Compile Include="ValidateCertificate.cs" />
Expand Down
30 changes: 30 additions & 0 deletions Examples/SetEncryptionProtocols.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Net;
using System.Net.FtpClient;
using System.Security.Authentication;

namespace Examples
{
public static class SetEncryptionProtocolsExample {
public static void ValidateCertificate()
{
using (FtpClient conn = new FtpClient())
{
conn.Host = "localhost";
conn.Credentials = new NetworkCredential("ftptest", "ftptest");
conn.EncryptionMode = FtpEncryptionMode.Explicit;

// Override the default protocols. The example line sets the protocols
// to support TLS 1.1 and TLS 1.2. These are only available if the
// executable targets .NET 4.5 (or higher). The framework does not enable these
// protocols by default.
//conn.SslProtocols = SslProtocols.Default | SslProtocols.Tls11 | SslProtocols.Tls12;

// Alternate example: Only support the latest level.
//conn.SslProtocols = SslProtocols.Tls12;

conn.Connect();
}
}
}
}
29 changes: 25 additions & 4 deletions System.Net.FtpClient/FtpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Security.Cryptography.X509Certificates;
using System.Globalization;
using System.Net.FtpClient.Extensions;
using System.Security.Authentication;

namespace System.Net.FtpClient {
/// <summary>
Expand Down Expand Up @@ -517,6 +518,22 @@ public bool DataConnectionEncryption {
}
}

private SslProtocols m_SslProtocols = SslProtocols.Default;
/// <summary>
/// Encryption protocols to use. Only valid if EncryptionMode property is not equal to FtpSslMode.None.
/// Default value is .NET Framework defaults from SslStream class.
/// </summary>
[FtpControlConnectionClone]
public SslProtocols SslProtocols
{
get {
return m_SslProtocols;
}
set {
m_SslProtocols = value;
}
}

FtpSslValidation m_sslvalidate = null;
/// <summary>
/// Event is fired to validate SSL certificates. If this event is
Expand Down Expand Up @@ -805,7 +822,8 @@ public virtual void Connect() {

if (EncryptionMode == FtpEncryptionMode.Implicit)
m_stream.ActivateEncryption(Host,
m_clientCerts.Count > 0 ? m_clientCerts : null);
m_clientCerts.Count > 0 ? m_clientCerts : null,
m_SslProtocols);

if (!(reply = GetReply()).Success) {
if (reply.Code == null) {
Expand All @@ -820,7 +838,8 @@ public virtual void Connect() {
if (!(reply = Execute("AUTH TLS")).Success)
throw new FtpSecurityNotAvailableException("AUTH TLS command failed.");
m_stream.ActivateEncryption(Host,
m_clientCerts.Count > 0 ? m_clientCerts : null);
m_clientCerts.Count > 0 ? m_clientCerts : null,
m_SslProtocols);
}

if (m_credentials != null) {
Expand Down Expand Up @@ -1149,7 +1168,8 @@ FtpDataStream OpenPassiveDataStream(FtpDataConnectionType type, string command,
// this needs to take place after the command is executed
if (m_dataConnectionEncryption && m_encryptionmode != FtpEncryptionMode.None)
stream.ActivateEncryption(m_host,
this.ClientCertificates.Count > 0 ? this.ClientCertificates : null);
this.ClientCertificates.Count > 0 ? this.ClientCertificates : null,
m_SslProtocols);

return stream;
}
Expand Down Expand Up @@ -1240,7 +1260,8 @@ FtpDataStream OpenActiveDataStream(FtpDataConnectionType type, string command, l

if (m_dataConnectionEncryption && m_encryptionmode != FtpEncryptionMode.None)
stream.ActivateEncryption(m_host,
this.ClientCertificates.Count > 0 ? this.ClientCertificates : null);
this.ClientCertificates.Count > 0 ? this.ClientCertificates : null,
m_SslProtocols);

stream.SetSocketOption(Sockets.SocketOptionLevel.Socket, Sockets.SocketOptionName.KeepAlive, m_keepAlive);
stream.ReadTimeout = m_dataConnectionReadTimeout;
Expand Down
28 changes: 20 additions & 8 deletions System.Net.FtpClient/FtpSocketStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -627,23 +627,35 @@ public void Connect(string host, int port, FtpIpVersion ipVersions) {
}

/// <summary>
/// Activates SSL on this stream. Fires the ValidateCertificate event. If this event is
/// not handled and there are SslPolicyErrors present, the certificate will not be
/// accepted.
/// Activates SSL on this stream using default protocols. Fires the ValidateCertificate event.
/// If this event is not handled and there are SslPolicyErrors present, the certificate will
/// not be accepted.
/// </summary>
/// <param name="targethost">The host to authenticate the certiciate against</param>
public void ActivateEncryption(string targethost) {
ActivateEncryption(targethost, null);
ActivateEncryption(targethost, null, SslProtocols.Default);
}

/// <summary>
/// Activates SSL on this stream. Fires the ValidateCertificate event. If this event is
/// not handled and there are SslPolicyErrors present, the certificate will not be
/// accepted.
/// Activates SSL on this stream using default protocols. Fires the ValidateCertificate event.
/// If this event is not handled and there are SslPolicyErrors present, the certificate will
/// not be accepted.
/// </summary>
/// <param name="targethost">The host to authenticate the certiciate against</param>
/// <param name="clientCerts">A collection of client certificates to use when authenticating the SSL stream</param>
public void ActivateEncryption(string targethost, X509CertificateCollection clientCerts) {
ActivateEncryption(targethost, clientCerts, SslProtocols.Default);
}

/// <summary>
/// Activates SSL on this stream using the specified protocols. Fires the ValidateCertificate event.
/// If this event is not handled and there are SslPolicyErrors present, the certificate will
/// not be accepted.
/// </summary>
/// <param name="targethost">The host to authenticate the certiciate against</param>
/// <param name="clientCerts">A collection of client certificates to use when authenticating the SSL stream</param>
/// <param name="sslProtocols">A bitwise parameter for supported encryption protocols.</param>
public void ActivateEncryption(string targethost, X509CertificateCollection clientCerts, SslProtocols sslProtocols) {
if (!IsConnected)
throw new InvalidOperationException("The FtpSocketStream object is not connected.");

Expand All @@ -663,7 +675,7 @@ public void ActivateEncryption(string targethost, X509CertificateCollection clie
}));

auth_start = DateTime.Now;
m_sslStream.AuthenticateAsClient(targethost, clientCerts, SslProtocols.Default, true);
m_sslStream.AuthenticateAsClient(targethost, clientCerts, sslProtocols, true);

auth_time_total = DateTime.Now.Subtract(auth_start);
FtpTrace.WriteLine("Time to activate encryption: {0}h {1}m {2}s, Total Seconds: {3}.",
Expand Down

0 comments on commit 4f72ff7

Please sign in to comment.