We are trying to connect to IBM MQ Server v 9.1.0.x. from RHEL 8.3 using .net core 3.1 and IBMMQDotnetClient 9.2.0.1 standard library from nuget.
We are stuck on getting CompCode: 2 Reason: 2059 error.
We know what is the reason: during ssl negotiation cipher spec is set to TLS_RSA_WITH_AES_128_CBC_SHA256 but the channel has it set to TLS_RSA_WITH_AES_256_CBC_SHA256.
ERR*.TRC
CommentInsert2(TLS_RSA_WITH_AES_256_CBC_SHA256)
CommentInsert3(TLS_RSA_WITH_AES_128_CBC_SHA256)
AMQ9631E: The CipherSpec negotiated during the SSL handshake does not match the required CipherSpec for channel
We had the same issue on Windows but doing
Disable-TlsCipherSuite -Name TLS_RSA_WITH_AES_128_CBC_SHA256
has resolved the issue.
What we've done already:
- We are specifying SSL_CIPHER_SPEC_PROPERTY as TLS_RSA_WITH_AES_256_CBC_SHA256.
Unfortunately it is ignored, as we are using managed client (MQC.TRANSPORT_MQSERIES_MANAGED) it's the only valid option for managed library. All security calls are transferred to internal security providers (Schanel/SslStreams on Windows and OpenSsl on Linux).
We know that we should alter cipher policy on Linux, do you have any idea how to:
- Disable TLS_RSA_WITH_AES_128_CBC_SHA256 on RHEL?
UPDATE
Disable-TlsCipherSuite -Name TLS_RSA_WITH_AES_128_CBC_SHA256
is a Powershell cmd.
UPDATE 1
On Linux (RHEL8.3) During handshake my frame looks like:
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8)
Cipher Suite: TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xccaa)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x006b)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x0067)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
**Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)**
**Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)**
Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
UPDATE 2
We managed to force cipher used during negotiation and then during MakeSecuredConnection. Unfortunately it's only doable on .NET5.0 and hack in MakeSecureConnection is needed.
I tried the same approach using .net core 3.1 but failed probably because of use of AuthenticateAsClientAsync.
Here is .NET5.0 IBM MQ Client 9.2.0.1 hack
- Decompile the code of IBMMQClient (amqmdnetstd.dll)
- Mark .csproj as .NET5.0
<TargetFramework>net5.0</TargetFramework>
- Edit
MakeSecureConnection
method in classMQEncryptedSocket
as follows
only .NET5.0
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
stream.AuthenticateAsClient("*", x509Certificate2Collection, sslProtocol, sslCertRevocationCheck);
}
else
{
//stream.AuthenticateAsClient("*", x509Certificate2Collection, sslProtocol, sslCertRevocationCheck);
var sslClientOptions = new SslClientAuthenticationOptions()
{
CertificateRevocationCheckMode = sslCertRevocationCheck ? X509RevocationMode.Offline : X509RevocationMode.NoCheck,
ClientCertificates = x509Certificate2Collection,
EnabledSslProtocols = sslProtocol,
TargetHost = "*",
RemoteCertificateValidationCallback =ClientValidatingServerCertificate,
LocalCertificateSelectionCallback = FixClientCertificate,
CipherSuitesPolicy = new CipherSuitesPolicy(new List<TlsCipherSuite>() { Enum.Parse<TlsCipherSuite>(cipherSpec) })
};
TrText(method, $"Setting Cipher for AuthenticateAsClient {string.Join(':',sslClientOptions.CipherSuitesPolicy.AllowedCipherSuites)}");
stream.AuthenticateAsClient(sslClientOptions);
}
for .net core 3.1 you have to call
stream.AuthenticateAsClientAsync(sslClientOptions);
Since there is no method AuthenticateAsClient
overload accepting SslClientAuthenticationOptions
parameter.
.net standard 2.0 and 2.1 don't have CipherSuitesPolicy parameter in class SslClientAuthenticationOptions
that's why I had to move the library from .net standard 2.0 to .net5.0 (with success) and .net core 3.1 without.
Do you have any clue how is it possible to make it work on .net core 3.1?