Skip to content

Commit 4577442

Browse files
authored
Merge pull request #766 from rabbitmq/rabbitmq-dotnet-client-764
Fall back to TLSv1.2 when System.Security.Authentication.SslProtocols.None is disabled/unavailable
2 parents 29e73bc + 304f976 commit 4577442

File tree

3 files changed

+36
-13
lines changed

3 files changed

+36
-13
lines changed

projects/client/RabbitMQ.Client/src/client/api/SslHelper.cs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
using System;
4242
using System.IO;
4343
using System.Net.Security;
44+
using System.Security.Authentication;
4445
using System.Security.Cryptography.X509Certificates;
4546

4647
namespace RabbitMQ.Client
@@ -59,21 +60,32 @@ private SslHelper(SslOption sslOption)
5960
}
6061

6162
/// <summary>
62-
/// Upgrade a Tcp stream to an Ssl stream using the SSL options provided.
63+
/// Upgrade a Tcp stream to an Ssl stream using the TLS options provided.
6364
/// </summary>
64-
public static Stream TcpUpgrade(Stream tcpStream, SslOption sslOption)
65+
public static Stream TcpUpgrade(Stream tcpStream, SslOption options)
6566
{
66-
var helper = new SslHelper(sslOption);
67+
var helper = new SslHelper(options);
6768

6869
RemoteCertificateValidationCallback remoteCertValidator =
69-
sslOption.CertificateValidationCallback ?? helper.CertificateValidationCallback;
70+
options.CertificateValidationCallback ?? helper.CertificateValidationCallback;
7071
LocalCertificateSelectionCallback localCertSelector =
71-
sslOption.CertificateSelectionCallback ?? helper.CertificateSelectionCallback;
72+
options.CertificateSelectionCallback ?? helper.CertificateSelectionCallback;
7273

7374
var sslStream = new SslStream(tcpStream, false, remoteCertValidator, localCertSelector);
7475

75-
sslStream.AuthenticateAsClientAsync(sslOption.ServerName, sslOption.Certs, sslOption.Version,
76-
sslOption.CheckCertificateRevocation).GetAwaiter().GetResult();
76+
Action<SslOption> TryAuthenticating = (SslOption opts) => {
77+
sslStream.AuthenticateAsClientAsync(opts.ServerName, opts.Certs, opts.Version,
78+
opts.CheckCertificateRevocation).GetAwaiter().GetResult();
79+
};
80+
try {
81+
TryAuthenticating(options);
82+
} catch(ArgumentException e) when (e.ParamName == "sslProtocolType" && options.Version == SslProtocols.None) {
83+
// SslProtocols.None is dysfunctional in this environment, possibly due to TLS version restrictions
84+
// in the app context, system or .NET version-specific behavior. See rabbitmq/rabbitmq-dotnet-client#764
85+
// for background.
86+
options.UseFallbackTlsVersions();
87+
TryAuthenticating(options);
88+
}
7789

7890
return sslStream;
7991
}

projects/client/RabbitMQ.Client/src/client/api/SslOption.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public SslOption()
7575
}
7676

7777
/// <summary>
78-
/// Retrieve or set the set of ssl policy errors that are deemed acceptable.
78+
/// Retrieve or set the set of TLS policy errors that are deemed acceptable.
7979
/// </summary>
8080
public SslPolicyErrors AcceptablePolicyErrors { get; set; }
8181

@@ -90,13 +90,13 @@ public SslOption()
9090
public string CertPath { get; set; }
9191

9292
/// <summary>
93-
/// An optional client specified SSL certificate selection callback. If this is not specified,
93+
/// An optional client specified TLS certificate selection callback. If this is not specified,
9494
/// the first valid certificate found will be used.
9595
/// </summary>
9696
public LocalCertificateSelectionCallback CertificateSelectionCallback { get; set; }
9797

9898
/// <summary>
99-
/// An optional client specified SSL certificate validation callback. If this is not specified,
99+
/// An optional client specified TLS certificate validation callback. If this is not specified,
100100
/// the default callback will be used in conjunction with the <see cref="AcceptablePolicyErrors"/> property to
101101
/// determine if the remote server certificate is valid.
102102
/// </summary>
@@ -135,19 +135,30 @@ public X509CertificateCollection Certs
135135
public bool CheckCertificateRevocation { get; set; }
136136

137137
/// <summary>
138-
/// Flag specifying if Ssl should indeed be used.
138+
/// Flag specifying if TLS should indeed be used.
139139
/// </summary>
140140
public bool Enabled { get; set; }
141141

142142
/// <summary>
143143
/// Retrieve or set server's Canonical Name.
144-
/// This MUST match the CN on the Certificate else the SSL connection will fail.
144+
/// This MUST match the Subject Alternative Name or CN on the Certificate else the TLS connection will fail.
145145
/// </summary>
146146
public string ServerName { get; set; }
147147

148148
/// <summary>
149149
/// Retrieve or set the Ssl protocol version.
150150
/// </summary>
151151
public SslProtocols Version { get; set; }
152+
153+
/// <summary>
154+
/// Reconfigures the instance to enable/use TLSv1.2.
155+
/// Only used in environments where System.Security.Authentication.SslProtocols.None
156+
/// is unavailable or effectively disabled, as reported by System.Net.ServicePointManager.
157+
/// </summary>
158+
internal SslProtocols UseFallbackTlsVersions()
159+
{
160+
this.Version = SslProtocols.Tls12;
161+
return Version;
162+
}
152163
}
153164
}

projects/client/Unit/src/unit/APIApproval.Approve.approved.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ namespace RabbitMQ.Client
548548
}
549549
public class SslHelper
550550
{
551-
public static System.IO.Stream TcpUpgrade(System.IO.Stream tcpStream, RabbitMQ.Client.SslOption sslOption) { }
551+
public static System.IO.Stream TcpUpgrade(System.IO.Stream tcpStream, RabbitMQ.Client.SslOption options) { }
552552
}
553553
public class SslOption
554554
{

0 commit comments

Comments
 (0)