How to force CipherSpec to specific value connecting to IBM MQ from RHEL using .net core. Get rid of CompCode: 2 Reason: 2059

Viewed 1639

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:

  1. 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:

  1. 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

  1. Decompile the code of IBMMQClient (amqmdnetstd.dll)
  2. Mark .csproj as .NET5.0 <TargetFramework>net5.0</TargetFramework>
  3. Edit MakeSecureConnection method in class MQEncryptedSocket 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?

1 Answers

I had the same issue when connecting with .NET MQ client to a channel using TLS_RSA_WITH_AES_256_CBC_SHA256 cipher.

In the MQ server logs I saw that my client tried to connect with TLS_RSA_WITH_AES_256_GCM_SHA384 even if I was setting the cipher spec to TLS_RSA_WITH_AES_256_CBC_SHA256 in my code.

cf.SetStringProperty(XMSC.WMQ_SSL_CIPHER_SPEC, “TLS_RSA_WITH_AES_256_CBC_SHA256”);

To solve it I had to set the system default cipher in the file /etc/ssl/openssl.cnf to AES256-SHA256.

[system_default_sect]
…
CipherString = AES256-SHA256

My application is built on .NET 6.

Related