Description of problem: Qpid python client should verify broker hostname against the server certificate before connecting the broker, if "ssl_skip_hostname_check" was set to "false" value. In case "ssl_trustfile" is set correctly, verification succeeds; if the "ssl_trustfile" is an invalid file, verification fails (this behavior seems to be right). However if "ssl_trustfile" is not given (and "ssl_skip_hostname_check" has still value "false"), the hostname verification against the server certificate is successful too, although there is no given certificate to authenticate the remote server. Version-Release number of selected component (if applicable): # rpm -qa | grep qpid qpid-java-common-0.23-4.el6.noarch qpid-cpp-client-devel-0.22-29.el6.i686 rh-qpid-cpp-tests-0.22-29.el6.i686 qpid-java-amqp-0-10-client-jms-0.23-4.el6.noarch qpid-qmf-0.22-24.el6.i686 qpid-cpp-server-rdma-0.22-29.el6.i686 qpid-java-example-0.23-4.el6.noarch qpid-snmpd-1.0.0-14.el6.i686 qpid-cpp-client-0.22-29.el6.i686 python-qpid-qmf-0.22-24.el6.i686 qpid-cpp-server-devel-0.22-29.el6.i686 ruby-qpid-qmf-0.22-24.el6.i686 qpid-cpp-server-xml-0.22-29.el6.i686 qpid-java-client-0.23-4.el6.noarch qpid-jca-0.22-1.el6.noarch qpid-proton-c-devel-0.5-9.el6.i686 qpid-cpp-client-devel-docs-0.22-29.el6.noarch qpid-cpp-client-rdma-0.22-29.el6.i686 qpid-cpp-debuginfo-0.22-16.el6.i686 qpid-tools-0.22-7.el6.noarch qpid-cpp-server-store-0.22-29.el6.i686 perl-qpid-0.22-7.el6.i686 qpid-jca-xarecovery-0.22-1.el6.noarch qpid-proton-c-0.5-9.el6.i686 qpid-cpp-server-0.22-29.el6.i686 qpid-cpp-server-ssl-0.22-29.el6.i686 python-qpid-0.22-8.el6.noarch qpid-cpp-client-ssl-0.22-29.el6.i686 qpid-cpp-server-ha-0.22-29.el6.i686 How reproducible: 100% Steps to Reproduce: 1. Generate "client.pem" certificate. 2. Run a broker over SSL. 3. Try to send a message; you can use the attached reproducer: ./qc2_spout.py --broker <hostname>:5671 --connection-options "{ username : 'guest', ssl_certfile : <path_to_client.pem>, protocol : 'amqp0-10', sasl_mechanisms : 'DIGEST-MD5', ssl_skip_hostname_check : 'false', password : 'guest', transport : 'ssl' }" --count 1 --sync-mode None "amq.topic;{}" Actual results: The client connects the broker. Expected results: The client should fail due to unsuccessful server hostname verification. Additional info: Broker configuration: ssl-require-client-authentication=yes data-dir=/var/lib/qpidd log-to-file=/var/lib/qpidd/qpidd.log ssl-cert-name=server auth=yes acl-file=/etc/qpid/qpidd.acl log-enable=info+ ssl-cert-password-file=<path_to_the_password_file> port=5672 ssl-port=5671 ssl-cert-db=<path_to_the_certdb>
Created attachment 833118 [details] bz reproducer Try to send a message: ./spout.py --broker <hostname>:5671 --connection-options "{ username : 'guest', ssl_certfile : <path_to_client.pem>, protocol : 'amqp0-10', sasl_mechanisms : 'DIGEST-MD5', ssl_skip_hostname_check : 'false', password : 'guest', transport : 'ssl' }" --count 1 "amq.topic;{}"
Ken, please assess.
According to the python docs: "The parameter cert_reqs specifies whether a certificate is required from the other side of the connection, and whether it will be validated if provided. It must be one of the three values CERT_NONE (certificates ignored), CERT_OPTIONAL (not required, but validated if provided), or CERT_REQUIRED (required and validated). If the value of this parameter is not CERT_NONE, then the ca_certs parameter [our ssl_trustfile parameter] must point to a file of CA certificates." We support only CERT_NONE (if no ssl_trustfile given) or CERT_REQUIRED (ssl_trustfile given). CERT_OPTIONAL is a security risk, and is not used. So our python client only receives the cert containing a hostname if ssl_trustfile is given. In other words, if ssl_trustfile is not given, then there will not be a hostname available to validate. But the behavior as described above can be confusing. Perhaps a warning should be logged if a user does not supply an ssl_trustfile and explicitly states "skip_hostname_check" == False (as opposed to not providing the parameter - as the default is _False_ anyways) As far a security is concerned: if no ssl_trustfile is given, checking the hostname would provide a false sense of security. Without a valid ssl_trustfile, nothing can be securely verified.
Created attachment 917919 [details] Assume if skip_hostname_check is set to false, user wants ssl Proposed patch. If the user has explicitly set the skip_hostname_check flag to false, assume they want a secure connection. If the trustfile is not also given, then a "qpid.messaging.exceptions.ConnectError: [Errno 111] Connection refused" is raised.
Ken, can you review the attached patch. If you concur that we should raise an exception when skip_hostname_check is explicitly set to false and no trustfile is given, then can you commit the patch upstream per Justin's request?
Created attachment 918475 [details] Distinguish between the default value of ssl_skip_hostname_check and manually setting the value to false New patch that only raises an exception if the user explicitly sets the flag, as opposed to the flag getting the default value.
Qpid python client requires to have a path to the certification authority's certificate and tries to verify the server certificate before connecting the broker, if "ssl_skip_hostname_check" was set to "false" value. Verified on Rhel6.6-i686 and x86_64 on package python-qpid-0.30-3. --> 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. https://rhn.redhat.com/errata/RHEA-2015-0805.html