Description of problem: The certificate file (passed with 'ssl_certfile' connection option) may contain the private key. In some cases, you can store the private key separate from the certificate. In that case, you'd have to also specify 'ssl_key' connection option and pass the separate keyfile. Providing the keyfile separately from the certificate file is not working, please see Steps to Reproduce and Additional info below. Version-Release number of selected component (if applicable): python-qpid-0.18-4.el5 qpid-tools-0.18-7.el5 How reproducible: 100% Steps to Reproduce: 1. Setup SSL broker requiring client authentication 2. Export client's certificate from the nss db in PEM format (use -nokeys option of openssl pkcs12) 3. Export client's private key from the nss db in PEM format (use -nocerts option of openssl pkcs12) 4. Try to connects with python client (ie. qpid-stat), provide the file exported in step2 to '--ssl-certificate' option and the file exported in step3 to '--ssl-key' option 5. Failed: ConnectError - SSL_CTX_use_PrivateKey_file error Actual results: Providing the keyfile separately from the certificate file is not working. Expected results: Providing the keyfile separately from the certificate file is working as expected. Additional info: /etc/qpidd.conf: cluster-mechanism=DIGEST-MD5 ANONYMOUS auth=yes ssl-cert-password-file=/var/lib/qpidd/ssl_pw_file ssl-cert-db=/var/lib/qpidd/qpid_nss_db ssl-cert-name="server_dhcp-37-228.lab.eng.brq.redhat.com" ssl-require-client-authentication=yes # pk12util -o /tmp/certkey.p12 -n "client" -d /var/lib/qpidd/qpid_nss_db/ -W "" pk12util: PKCS12 EXPORT SUCCESSFUL # openssl pkcs12 -in /tmp/certkey.p12 -out keycert.pem -nodes -clcerts -passin pass:"" MAC verified OK # openssl pkcs12 -in /tmp/certkey.p12 -out certonly.pem -nodes -nokeys -clcerts -passin pass:"" MAC verified OK # openssl pkcs12 -in /tmp/certkey.p12 -out keyonly.pem -nodes -nocerts -passin pass:"" MAC verified OK # qpid-stat -b amqps://$(hostname):5671 -q --ssl-certificate=${PWD}/keycert.pem Queues queue dur autoDel excl msg msgIn msgOut bytes bytesIn bytesOut cons bind ========================================================================================================================= 9763f1ad-f12c-8b41-b266-d4a83a487a19:0.0 Y Y 0 0 0 0 0 0 1 2 # qpid-stat -b amqps://$(hostname):5671 -q --ssl-certificate=${PWD}/certonly.pem Failed: ConnectError - SSL_CTX_use_PrivateKey_file error # qpid-stat -b amqps://$(hostname):5671 -q --ssl-certificate=${PWD}/certonly.pem --ssl-key=${PWD}/keyonly.pem Failed: ConnectError - SSL_CTX_use_PrivateKey_file error # qpid-stat -b amqps://$(hostname):5671 -q --ssl-certificate=${PWD}/certonly.pem --ssl-key=${PWD}/keycert.pem Failed: ConnectError - SSL_CTX_use_PrivateKey_file error
Hi Petr, Is there a difference in behavior when running on RHEL 5 vs RHEL 6? The underlying python SSL libraries have changed between the two. -K
No, the behaviour is the same on both RHEL 5 and RHEL 6.
I think I've found a simple coding error that is the cause of this bug: The qpid tools are based on the qpid python client library. This library exports a Connection object that the tools use to connect to the broker. This connection object is supplied all SSL related configuration parameters for the connection. Those tools which accept the separate SSL keyfile parameter are passing it in the wrong argument to Connection. Connection accepts this argument using the name "ssl_keyfile". The tools are incorrectly providing this parameter using the name "ssl_key". Thus the connection never "sees" the keyfile. A "grep" of "ssl_*" in qpid/tools: find . -type f -print0 | xargs -0 -e grep -n -i "ssl_" ./src/py/qpid-route:141: if opts.ssl_certificate: ./src/py/qpid-route:142: config._conn_options['ssl_certfile'] = opts.ssl_certificate ./src/py/qpid-cluster:298: if opts.ssl_certificate: ./src/py/qpid-cluster:299: conn_options['ssl_certfile'] = opts.ssl_certificate ./src/py/qpid-tool:180: self.broker = self.session.addBroker(self.url, ssl_certfile=cert) ./src/py/qpid-printevents:150: if options.ssl_certificate: ./src/py/qpid-printevents:151: conn_options['ssl_certfile'] = options.ssl_certificate ./src/py/qpid-printevents:152: if options.ssl_key: ./src/py/qpid-printevents:153: conn_options['ssl_key'] = options.ssl_key ./src/py/qpid-config:318: if opts.ssl_certificate: ./src/py/qpid-config:319: conn_options['ssl_certfile'] = opts.ssl_certificate ./src/py/qpid-config:320: if opts.ssl_key: ./src/py/qpid-config:321: conn_options['ssl_key'] = opts.ssl_key ./src/py/qpid-stat:108: if opts.ssl_certificate: ./src/py/qpid-stat:109: conn_options['ssl_certfile'] = opts.ssl_certificate ./src/py/qpid-stat:110: if opts.ssl_key: ./src/py/qpid-stat:111: conn_options['ssl_key'] = opts.ssl_key ./src/py/qpid-queue-stats:136: if options.ssl_certificate: ./src/py/qpid-queue-stats:137: conn_options['ssl_certfile'] = options.ssl_certificate ./src/py/qpid-ha:61: if opts.ssl_certificate: ./src/py/qpid-ha:62: conn_options['ssl_certfile'] = opts.ssl_certificate ./src/py/qpid-ha:63: if opts.ssl_key: ./src/py/qpid-ha:64: conn_options['ssl_key'] = opts.ssl_key Note the use of 'ssl_key' as the options name - that should be 'ssl_keyfile'. Not to mention the tools that don't even allow the keyfile to be specified - that's an additional problem.
Confirmed, when the client private key is provided to the Connection object separately using 'ssl_keyfile' argument instead of 'ssl_key' (as qpid-tools do), the connection is successful (the argument works as expected). -> Changing component to qpid-tools. I also believe that fix for this issue is easy and may be provided with 2.3 release, thus adding 2.3.0? and blocker?
(In reply to comment #3) > Not to mention the tools that don't even allow the keyfile to be specified - > that's an additional problem. Note: there is already a bug reported for this issue, please see bug 895515
Upstream JIRA: https://issues.apache.org/jira/browse/QPID-4554
Fix pushed to private BZ branch on mrg repo (0.18-mrg-kgiusti-bz895535): http://mrg1.lab.bos.redhat.com/git/?p=qpid.git;a=commit;h=fb9108f75585bc17d03952cabac83e4bc634c26c
Automated test shows that the '--ssl-key' option is still not working properly for all the management tools. However all the qpid-tools were changed to support the correct connection option ('ssl_keyfile' instead of 'ssl_key'). It solves the issue on for qpid-config and qpid-stat. The ssl-key option is still not working properly for the following management tools: qpid-route qpid-cluster qpid-queue-stats * Note qpid-tool still do not support '--ssl-key' option, please see Bug 895515 for details. I believe that this issue is caused by the fact that qpid-stat and qpid-config pass the ssl options to the connection object, ie. Connection.establish(self.url, **conn_options), this is working fine. But when the options are passed to another object (what the other qpid-tools do), ie.: BrokerManager the options do not work. How the qpid-tools pass the connection options: /usr/bin/qmf-tool self.connection = cqpid.Connection(self.url, **self.conn_options) /usr/bin/qpid-cluster def __init__(self, config, conn_options): self.broker = self.qmf.addBroker(brokerUrl, self.config._connTimeout, **self.conn_options) bm = BrokerManager(config, conn_options) /usr/bin/qpid-cluster-store /usr/bin/qpid-config self.conn = Connection.establish(self.url, **conn_options) /usr/bin/qpid-printevents er = EventReceiver(printer, host, conn_options) /usr/bin/qpid-queue-stats def __init__(self, host, conn_options): self.broker = self.session.addBroker(self.url, **conn_options) bm = BrokerManager(host, conn_options) /usr/bin/qpid-route self.broker = self.qmf.addBroker(localBroker, config._connTimeout, **config._conn_options) /usr/bin/qpid-stat self.connection = Connection.establish(self.url, **conn_options)
test transcript: <snip> qpid-config: CMD: qpid-config -b amqps://127.0.0.1:6667 --ssl-certificate guest_cert --ssl-key=guest_pkey Total Exchanges: 8 topic: 3 headers: 1 fanout: 1 direct: 3 Total Queues: 6 durable: 0 non-durable: 6 PASS qpid-stat: CMD: qpid-stat -q -b amqps://127.0.0.1:6667 --ssl-certificate guest_cert --ssl-key=guest_pkey Queues queue dur autoDel excl msg msgIn msgOut bytes bytesIn bytesOut cons bind ========================================================================================================================= c22f2063-3c8e-4d47-af91-125131b1b35b:0.0 Y Y 0 0 0 0 0 0 1 2 qpid-perftest0 0 10 10 0 10.2k 10.2k 0 1 qpid-perftest_pub_done 0 1 1 0 16 16 0 1 qpid-perftest_pub_start 0 1 1 0 5 5 0 1 qpid-perftest_sub_done 0 1 1 0 17 17 0 1 qpid-perftest_sub_ready 0 1 1 0 5 5 0 1 PASS qpid-route: CMD: qpid-route route map amqps://127.0.0.1:6667 --ssl-certificate guest_cert --ssl-key=guest_pkey Failed: sslerror - SSL_CTX_use_PrivateKey_file error FAIL qpid-cluster: CMD: qpid-cluster amqps://127.0.0.1:6667 --ssl-certificate guest_cert --ssl-key=guest_pkey Failed: sslerror - SSL_CTX_use_PrivateKey_file error FAIL qpid-queue-stats: FAIL Queue Name Sec Depth Enq Rate Deq Rate ======================================================================================== *** Error: Exception during connection setup: sslerror - SSL_CTX_use_PrivateKey_file error, retrying... qpid-printevents: PASS Fri Feb 8 10:41:10 2013 NOTIC qpid-printevents:brokerConnected broker=amqps://127.0.0.1:6667 Fri Feb 8 10:41:10 2013 org.apache.qpid.broker:bind exName=qmf.default.topic args={} qName=b313824d-1c21-6440-9cff-076c3caf8502:0.0 user=anonymous@QPID key=agent.ind.event.*.*.*.# rhost=127.0.0.1:6667-127.0.0.1:54273 </snip>
This issue has been fixed. Verified on rhel5.9 and rhel6.4 (x86_64, i386) packages used for testing: qpid-tools-0.18-8.el5 qpid-qmf-0.18-15.el5 python-qpid-0.18-4.el5 -> VERIFIED
Since the problem described in this bug report should be resolved in a recent advisory, it has been closed with a resolution of ERRATA. For information on the advisory, and where to find the updated files, follow the link below. If the solution does not work for you, open a new bug report. http://rhn.redhat.com/errata/RHSA-2013-0561.html