title: How to force CipherSpec to specific value connecting to IBM MQ from RHEL using .net core. Get rid of CompCode: 2 Reason: 2059
body: <p>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.</p>
  <p>We are stuck on getting CompCode: 2 Reason: 2059 error.</p>
  <p>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.<br />
  ERR*.TRC</p>
  <blockquote>
  <p>CommentInsert2(TLS_RSA_WITH_AES_256_CBC_SHA256)<br />
  CommentInsert3(TLS_RSA_WITH_AES_128_CBC_SHA256)<br />
  AMQ9631E: The CipherSpec negotiated during the SSL handshake does not match the
  required CipherSpec for channel</p>
  </blockquote>
  <p>We had the same issue on Windows but doing
  <code>Disable-TlsCipherSuite -Name TLS_RSA_WITH_AES_128_CBC_SHA256</code> has resolved the issue.</p>
  <p>What we've done already:</p>
  <ol>
  <li>We are specifying SSL_CIPHER_SPEC_PROPERTY as TLS_RSA_WITH_AES_256_CBC_SHA256.</li>
  </ol>
  <p>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).<br />
  We know that we should alter cipher policy on Linux, do you have any idea how to:</p>
  <ol>
  <li>Disable TLS_RSA_WITH_AES_128_CBC_SHA256 on RHEL?</li>
  </ol>
  <p><strong>UPDATE</strong><br />
  <code>Disable-TlsCipherSuite -Name TLS_RSA_WITH_AES_128_CBC_SHA256</code> is a Powershell cmd.</p>
  <p><strong>UPDATE 1</strong></p>
  <p>On Linux (RHEL8.3) During handshake my frame looks like:</p>
  <pre><code>    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)
  
  </code></pre>
  <p><strong>UPDATE 2</strong><br />
  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.<br />
  I tried the same approach using .net core 3.1 but failed probably because of use of AuthenticateAsClient<strong>Async</strong>.</p>
  <p>Here is .NET5.0 IBM MQ Client 9.2.0.1 hack</p>
  <ol>
  <li>Decompile the code of IBMMQClient (amqmdnetstd.dll)</li>
  <li>Mark .csproj as .NET5.0 <code>&lt;TargetFramework&gt;net5.0&lt;/TargetFramework&gt;</code></li>
  <li>Edit <code>MakeSecureConnection</code> method in class <code>MQEncryptedSocket</code> as follows</li>
  </ol>
  <p><strong>only .NET5.0</strong></p>
  <pre class="lang-cs prettyprint-override"><code>                if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                  {
                      stream.AuthenticateAsClient(&quot;*&quot;, x509Certificate2Collection, sslProtocol, sslCertRevocationCheck);
                  }
                  else
                  {
                      //stream.AuthenticateAsClient(&quot;*&quot;, x509Certificate2Collection, sslProtocol, sslCertRevocationCheck);
                      var sslClientOptions = new SslClientAuthenticationOptions()
                      {
                          CertificateRevocationCheckMode = sslCertRevocationCheck ? X509RevocationMode.Offline   : X509RevocationMode.NoCheck,
                          ClientCertificates = x509Certificate2Collection,
                          EnabledSslProtocols = sslProtocol, 
                          TargetHost = &quot;*&quot;,  
                          RemoteCertificateValidationCallback =ClientValidatingServerCertificate,
                          LocalCertificateSelectionCallback = FixClientCertificate,
                          CipherSuitesPolicy = new CipherSuitesPolicy(new List&lt;TlsCipherSuite&gt;() { Enum.Parse&lt;TlsCipherSuite&gt;(cipherSpec) })
                      };
                      TrText(method, $&quot;Setting Cipher for AuthenticateAsClient {string.Join(':',sslClientOptions.CipherSuitesPolicy.AllowedCipherSuites)}&quot;);
                      stream.AuthenticateAsClient(sslClientOptions);
                  }
  </code></pre>
  <p>for .net core 3.1 you have to call</p>
  <pre class="lang-cs prettyprint-override"><code>    stream.AuthenticateAsClientAsync(sslClientOptions); 
  </code></pre>
  <p>Since there is no method <code>AuthenticateAsClient</code> overload accepting <code>SslClientAuthenticationOptions</code> parameter.<br />
  .net standard 2.0 and 2.1 don't have CipherSuitesPolicy  parameter in class <code>SslClientAuthenticationOptions</code> 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.<br />
  Do you have any clue how is it possible to make it work on .net core 3.1?</p>