This is my first time working with IBM MQ. I have written a simple C# using .Net framewrok 4.8 code block to connect to a local queue with SSL enabled. I am using the IBMMQDotnetClient version 9.3.0 package.
using System;
using IBM.WMQ;
using System.Collections;
namespace MqClientTest
{
class Program
{
static void Main(string[] args)
{
var queueManagerName = "Queue_Manager";
var hostName = "localhost";
var channel = "Local_Channel";
var queueName = "Local_Queue";
var port = "5588";
var sslKeyRepository = "*SYSTEM";
var cipherSpec = "ECDHE_RSA_AES_256_CBC_SHA384";
Hashtable prop = new Hashtable();
prop.Add(MQC.HOST_NAME_PROPERTY, hostName);
prop.Add(MQC.PORT_PROPERTY, port);
prop.Add(MQC.CHANNEL_PROPERTY, channel);
prop.Add(MQC.CONNECT_OPTIONS_PROPERTY, MQC.MQCNO_RECONNECT);
prop.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
prop.Add(MQC.SSL_CERT_STORE_PROPERTY, sslKeyRepository);
prop.Add(MQC.SSL_CIPHER_SPEC_PROPERTY, "ECDHE_RSA_AES_256_CBC_SHA384");
foreach (DictionaryEntry de in prop)
{
Console.WriteLine("Key: {0}, Value: {1}", de.Key, de.Value);
}
try
{
var queueManager = new MQQueueManager(queueManagerName, prop);
MQQueue _queue = queueManager.AccessQueue(queueName, MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING);
Console.WriteLine("Connected");
}
catch (MQException ex)
{
Console.WriteLine("An IBM MQ error occurred: {0}, {1}", ex.Message.ToString(), ex.StackTrace.ToString());
Console.ReadKey();
}
catch (System.Exception ex)
{
Console.WriteLine("A System error occurred: {0}, {1}", ex.Message.ToString(), ex.StackTrace.ToString());
Console.ReadKey();
}
Console.ReadKey();
}
}
}
However, I keep encountering this error:
The CipherSpec negotiated during the SSL handshake does not match the required CipherSpec for channel 'Local_Channel'.
There is a mismatch between the CipherSpecs on the local and remote ends of channel 'Local_Channel'. The channel will not run until this mismatch is resolved. The CipherSpec required in the local channel definition is 'ECDHE_RSA_AES_256_CBC_SHA384'. The name of the CipherSpec negotiated during the SSL handshake is 'ECDHE_RSA_AES_256_GCM_SHA384'. A code is displayed if the name of the negotiated CipherSpec cannot be determined.
Change the channel definitions for 'Local_Channel' so the two ends have matching CipherSpecs and restart the channel. When using the 'ANY' type CipherSpecs ensure that the client CipherSpec value meets the requirements for the 'ECDHE_RSA_AES_256_CBC_SHA384' CipherSpec set on the channel 'Local_Channel'. If the client is set to use a minimum protocol ('ANY', '*_OR_HIGHER') CipherSpec, then the channel definition CipherSpec should be set to use the same minimum protocol CipherSpec, or a stronger, matching CipherSpec, to prevent the TLS handshake from using a higher protocol than is allowed by the channel definition CipherSpec. If the certificate in use by one end of the channel is a Global Server Certificate, then the negotiated CipherSpec may not match that specified on either end of the channel. This is because the SSL protocol allows a Global Server Certificate to automatically negotiate a higher level of encryption. In these cases specify a CipherSpec which meets the requirements of the Global Server Certificate.
I am not sure why it says the cipher spec negotiated during the SSL handshake is 'ECDHE_RSA_AES_256_GCM_SHA384' as you can see in my code, I have already hardcoded to "ECDHE_RSA_AES_256_CBC_SHA384".
Is there somwhere in windows server 2019 that I need to tweak to get this right? I have also tried to this https://community.ibm.com/community/user/communities/community-home/librarydocuments/viewdocument?DocumentKey=a3eeada6-9b61-4ec8-abe6-5bc61fdbaebc
Any pointers to resolve this will be much appreciated.
Kind regards, Colin
UPDATED: I finally used the unmanaged MQ Client to connect to the local Queue Manager with SSL (amqmdnet.dll)
using System.Collections;
using IBM.WMQ;
using System;
namespace MqClientUnmanaged
{
class Program
{
static void Main(string[] args)
{
var queueManagerName = "Local_Queue_Manager";
var hostName = "localhost";
var channel = "Local_Channel";
var queueName = "Local_Queue";
var port = "5588";
var sslKeyRepository = @"C:\ProgramData\IBM\MQ\server";
var cipherSpec = "ECDHE_RSA_AES_256_CBC_SHA384";
var certLabel = "ibmmqserver";
Hashtable prop = new Hashtable();
prop.Add(MQC.HOST_NAME_PROPERTY, hostName);
prop.Add(MQC.PORT_PROPERTY, port);
prop.Add(MQC.CHANNEL_PROPERTY, channel);
prop.Add(MQC.CONNECT_OPTIONS_PROPERTY, MQC.MQCNO_RECONNECT);
//prop.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
prop.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_CLIENT);
prop.Add(MQC.SSL_CERT_STORE_PROPERTY, sslKeyRepository);
prop.Add(MQC.SSL_CIPHER_SPEC_PROPERTY, cipherSpec);
prop.Add(MQC.CERT_LABEL_PROPERTY, certLabel);
//prop.Add("CertificateLabel", certLabel);
foreach (DictionaryEntry de in prop)
{
Console.WriteLine("Key: {0}, Value: {1}", de.Key, de.Value);
}
try
{
var queueManager = new MQQueueManager(queueManagerName, prop);
MQQueue _queue = queueManager.AccessQueue(queueName, MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING);
Console.WriteLine("Connected");
MQMessage retrievedMessage = new MQMessage();
MQGetMessageOptions gmo = new MQGetMessageOptions();
_queue.Get(retrievedMessage, gmo);
Console.WriteLine("The message is: {0}", retrievedMessage.ReadString(retrievedMessage.MessageLength));
Console.WriteLine(new string('*', 100));
}
catch (MQException ex)
{
Console.WriteLine("An IBM MQ error occurred: {0}, {1}", ex.Message.ToString(), ex.StackTrace.ToString());
Console.ReadKey();
}
catch (System.Exception ex)
{
Console.WriteLine("A System error occurred: {0}, {1}", ex.Message.ToString(), ex.StackTrace.ToString());
Console.ReadKey();
}
Console.ReadKey();
}
}
}
