Here is client trace RetreiveAndValidateSSLParams section, it seems like it is picking up the client cert:
16:15:58.967642 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- > RetrieveAndValidateSSLParams(MQConnectOptions) entry
16:15:58.967991 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d KeyStore is *USER
16:15:58.968268 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d CertificateLabel set from sslConfigOptions = ibmwebspheremqrbapp
16:15:58.968646 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d KeyResetCount is 0
16:15:58.968980 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d CertificationCheck = False
16:15:58.969231 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d Hostname is :my.mq.host.com
16:15:58.969690 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d CipherSpec value is TLS_AES_256_GCM_SHA384
16:15:58.970048 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d SSLPEERNAME value is CN=DEV_RB, OU=DEV, O=RB
16:15:58.970352 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- < RetrieveAndValidateSSLParams(MQConnectOptions) rc=OK exit
16:15:58.971846 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- > MakeSecuredConnection() entry
16:15:58.972182 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d Created an instance of SSLStreams
16:15:58.972471 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d Setting current certificate store as 'User'
16:15:58.972712 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d Linux so use My & CurrentUser
16:15:58.972996 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d Created store object to access certificates
16:15:58.973292 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d Opened store
16:15:58.973666 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d Accessing certificate - ibmwebspheremqrbapp
16:15:58.976958 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d Number of certificates in the store:1
16:15:58.978444 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d TLS12 supported - True
16:15:58.978747 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d TLS13 supported - True
16:15:58.979627 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d Cipherspec protocol version:TLS 1.3
16:15:58.980073 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d Setting SslProtol as Tls13
16:15:58.980351 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d Starting SSL Authentication
16:15:58.980700 28.0001 IBM.WMQ.MQClientCfg ----+----+ > GetStringValue(StringCfgProperty) entry [o] IBM.WMQ.MQClientCfg+StringCfgProperty
16:15:58.980986 28.0001 IBM.WMQ.MQClientCfg ----+----+ < GetStringValue(StringCfgProperty) rc=OK exit
16:15:58.981786 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d Server name is set to rb5f-pay5f-res5f-b.chl.mq.ibm.com
16:15:58.982661 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+----+ > FixClientCertificate(Object,String,X509CertificateCollection,X509Certificate,String[]) entry
16:15:58.982941 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+----+ d Client callback has been invoked to find client certificate
16:15:58.983224 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+----+ < FixClientCertificate(Object,String,X509CertificateCollection,X509Certificate,String[]) rc=OK exit
16:15:58.999198 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+----+ > FixClientCertificate(Object,String,X509CertificateCollection,X509Certificate,String[]) entry
16:15:58.999570 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+----+ d Client callback has been invoked to find client certificate
16:15:58.999840 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+----+ d Use the first certificate that is from an acceptable issuer.
16:15:59.000276 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+----+ < FixClientCertificate(Object,String,X509CertificateCollection,X509Certificate,String[]) rc=OK exit
16:15:59.003589 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+----+ > ClientValidatingServerCertificate(Object,X509Certificate,X509Chain,SslPolicyErrors) entry
16:15:59.004577 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- > ParseDN(String) entry
16:15:59.004878 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d DN String = CN=DEV_RB, OU=DEV, O=RB
16:15:59.005150 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=2
16:15:59.005438 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.005692 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.005968 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.006260 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.006519 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.006780 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.007049 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.007291 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=1
16:15:59.008372 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- > SetValue(String,String) entry
16:15:59.008668 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d RawSymbol =CN
16:15:59.008917 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d CN=DEV_RB
16:15:59.009160 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- < SetValue(String,String) rc=OK exit
16:15:59.009404 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=2
16:15:59.009699 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.009964 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.010221 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.010584 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.010909 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=1
16:15:59.011222 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- > SetValue(String,String) entry
16:15:59.011495 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d RawSymbol =OU
16:15:59.011788 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d OU=System.Collections.Generic.List`1[System.String]
16:15:59.012039 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- < SetValue(String,String) rc=OK exit
16:15:59.012279 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=2
16:15:59.012551 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.012806 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.013052 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.013292 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.013595 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- > SetValue(String,String) entry
16:15:59.013892 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d RawSymbol =O
16:15:59.014222 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d O=RB
16:15:59.014558 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- < SetValue(String,String) rc=OK exit
16:15:59.015106 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- < ParseDN(String) rc=OK exit
16:15:59.015528 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- > ParseDN(String) entry
16:15:59.015812 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d DN String = CN=DEV_RB, OU=DEV, O=RB
16:15:59.016093 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=2
16:15:59.016407 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.016691 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.016916 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.017196 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.017433 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.017698 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.017962 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.018196 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=1
16:15:59.018462 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- > SetValue(String,String) entry
16:15:59.018768 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d RawSymbol =CN
16:15:59.019029 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d CN=DEV_RB
16:15:59.019269 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- < SetValue(String,String) rc=OK exit
16:15:59.019533 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=2
16:15:59.019776 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.020013 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.020276 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.020576 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.020801 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=1
16:15:59.021057 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- > SetValue(String,String) entry
16:15:59.021322 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d RawSymbol =OU
16:15:59.021611 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d OU=System.Collections.Generic.List`1[System.String]
16:15:59.021900 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- < SetValue(String,String) rc=OK exit
16:15:59.022200 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=2
16:15:59.022564 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.022892 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.023243 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.023626 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d State=3
16:15:59.024180 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- > SetValue(String,String) entry
16:15:59.024687 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d RawSymbol =O
16:15:59.025039 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d O=RB
16:15:59.025489 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- < SetValue(String,String) rc=OK exit
16:15:59.025984 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- < ParseDN(String) rc=OK exit
16:15:59.027054 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- > IsMatchingPeerName(MQPeerNameMatching) entry
16:15:59.027794 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- > Wequals(String,String) entry
16:15:59.028100 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d Returning True
16:15:59.028375 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- < Wequals(String,String) rc=OK exit
16:15:59.028642 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- > Wequals(String,String) entry
16:15:59.028897 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d Returning True
16:15:59.029149 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- < Wequals(String,String) rc=OK exit
16:15:59.029520 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- > Wequals(String,String) entry
16:15:59.029828 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- d Returning True
16:15:59.030074 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+-- < Wequals(String,String) rc=OK exit
16:15:59.030329 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- d Return value = True
16:15:59.030618 28.0001 IBM.WMQ.Nmqi.MQPeerNameMatching ----+----+- < IsMatchingPeerName(MQPeerNameMatching) rc=OK exit
16:15:59.030998 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+----+ < ClientValidatingServerCertificate(Object,X509Certificate,X509Chain,SslPolicyErrors) rc=OK exit
16:15:59.031516 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- d SSL Authentication completed
16:15:59.031781 28.0001 IBM.WMQ.Nmqi.MQEncryptedSocket ----+---- < MakeSecuredConnection() rc=OK exit
------------------------------
Bjarki Björgúlfsson
------------------------------
Original Message:
Sent: Wed June 26, 2024 11:47 AM
From: Bjarki Björgúlfsson
Subject: Any solution to make XMS client (or base dotnet MQ client) on Linux to work with TLS and Client Auth
@Adam Burgess do you have any update on this? I'm having trouble getting the managed xms client library to present a client certificate to the server. I have only one pfx cert file inside $HOME/.dotnet/corefx/cryptography/x509stores/my/ and in the xms trace the client seems to picke it up but the server doesn't seem to get a valid cert from the client. My client is using NuGet Gallery | IBMXMSDotnetClient 9.3.5.1 and is running in a RedHat based linux container. The error on the server is:
06/25/2024 02:25:32 PM - Process(3197567.6352198) User(mqm) Program(amqrmppa)
Host(my.host.com) Installation(Installation1)
VRMF(9.2.0.3) QMgr(MY.QMAN)
Time(2024-06-25T14:25:32.311Z)
RemoteHost(XXX.XX.XX.XX)
CommentInsert1(MY_CHANNEL_NAME)
CommentInsert2(SSLCAUTH)
CommentInsert3(XXX.XX.XX.XX)
AMQ9637E: During handshake, the remote partner sent no certificate.
EXPLANATION:
The conversation cannot begin because a certificate has not been supplied by
the remote partner.
The channel name is 'MY_CHANNEL_NAME'.
The remote host is 'XXX.XX.XX.XX'.
If this error message is written on the receiving side of the channel, then the
channel attributes 'SSLCAUTH' caused the check to be made.
ACTION:
Look at the key repository on the remote side of this channel, and make sure
the appropriate certificates are present, with correct labels.
------------------------------
Bjarki Björgúlfsson
Original Message:
Sent: Wed November 30, 2022 12:12 PM
From: Adam Burgess
Subject: Any solution to make XMS client (or base dotnet MQ client) on Linux to work with TLS and Client Auth
I am wondering if anyone has any workarounds to make a production ready setup where an XMS client can connect using TLS from a non-Windows platform where TLS client authentication is enabled on the SVRCONN channel. The background is that the client certificate lookup for XMS (actually inherited from the base class) uses dotnet's standard library methods (I can provide more info if required) using managed mode, and since dotnet on Linux does not support FriendlyName in the certificate stores, the IBM standard solution for targetting the certificate and private key based on this field does not work - and in fact is silently ignored (e.g. default value ibmwebspheremq<user>). The certificate (and private key) picked by the client is silently an arbitrary one (the first picked from the user account's personal dotnet certificate store). Therefore the only way for this to work it seems is to force there to be only a single keystore file under $HOME/.dotnet/corefx/cryptography/x509stores/my/. In any environment where there may be multiple keystores for various uses, the only option would seem to be to override $HOME value to some carefully constructed directory containing only the single required keystore - not really a recommended or robust option (especially given that some dotnet calls seems to cause auto-generation of a local self-signed certificate set).
IBM support have finally confirmed to me that adjusting this behaviour requires an RFE and, believe it or not, that it is currently working as designed (despite this not being documented).
------------------------------
Adam Burgess
------------------------------