Red Hat Bugzilla – Bug 1520364
perl-LDAP not to default to TLS 1.0 in an explicit STARTTLS LDAP protocol upgrade
Last modified: 2018-10-30 03:54:56 EDT
+++ This bug was initially created as a clone of Bug #1519080 +++ [...] # vim slapd.conf TLSProtocolMin = 3.2 or 3.3 //TLS1.2 1.3. While 3.1(TLS1.0) works fine # smbldap-passwd user-name Cannot start TLS on LDAP connection: ldap://<>:389: SSL connect attempt failed with unknown error error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number [...] Steps to Reproduce: 1. Configure TLSProtocolMin 3.2 or 3.3 in slapd.conf 2. Run smbldap-passwd user-name 3. See the Error: Cannot start TLS on LDAP connection: ldap://<>:389: SSL connect attempt failed with unknown error error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number Actual results: TLS1.1, 1.2 cannot complete SSL handshake and connection establishment. Expected results: TLS1.1, 1.2 should work fine [...] --- Additional comment from Michael Starling on 2017-12-01 14:57:22 GMT --- I am using startTLS over 389 not LDAPS. I do not have a problem with openssl or client connections. The only failure I'm seeing is with Perl. With TLSProtocolMin 3.2 set in the directory I receive the following fatal error when connecting with Perl. When I set TLSProtocolMin 3.1 thinsg works as expected. use strict; use warnings; use diagnostics; use Net::LDAP; my $ldap_master = Net::LDAP->new("ldap1.example.com", port => '389', version => 3); $ldap_master->start_tls(); my $msg = $ldap_master->search(base => "dc=example,dc=com", filter => "(&(objectclass=posixaccount)(uid=*))", scope => "sub"); foreach my $entry ($msg->all_entries) { my $dn= $entry->dn; print($dn . "\n"); } New TCP connection #1: ldap1(42174) <-> ldap1(389) 1 1 0.0215 (0.0215) C>S Handshake ClientHello Version 3.1 cipher suites TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA TLS_DHE_RSA_WITH_AES_256_CBC_SHA TLS_DHE_DSS_WITH_AES_256_CBC_SHA TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA TLS_ECDH_anon_WITH_AES_256_CBC_SHA TLS_DH_anon_WITH_AES_256_CBC_SHA TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA TLS_ECDH_RSA_WITH_AES_256_CBC_SHA TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA TLS_RSA_WITH_AES_256_CBC_SHA TLS_RSA_WITH_CAMELLIA_256_CBC_SHA TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_DHE_RSA_WITH_SEED_CBC_SHA TLS_DHE_DSS_WITH_SEED_CBC_SHA TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA TLS_ECDH_anon_WITH_AES_128_CBC_SHA TLS_DH_anon_WITH_AES_128_CBC_SHA TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA TLS_DH_anon_WITH_SEED_CBC_SHA TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA TLS_DH_anon_WITH_3DES_EDE_CBC_SHA TLS_ECDH_RSA_WITH_AES_128_CBC_SHA TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_RSA_WITH_SEED_CBC_SHA TLS_RSA_WITH_CAMELLIA_128_CBC_SHA TLS_RSA_WITH_3DES_EDE_CBC_SHA TLS_RSA_WITH_IDEA_CBC_SHA TLS_ECDHE_RSA_WITH_RC4_128_SHA TLS_ECDHE_ECDSA_WITH_RC4_128_SHA TLS_ECDH_anon_WITH_RC4_128_SHA TLS_DH_anon_WITH_RC4_128_MD5 TLS_ECDH_RSA_WITH_RC4_128_SHA TLS_ECDH_ECDSA_WITH_RC4_128_SHA TLS_RSA_WITH_RC4_128_SHA TLS_RSA_WITH_RC4_128_MD5 TLS_DHE_RSA_WITH_DES_CBC_SHA TLS_DHE_DSS_WITH_DES_CBC_SHA TLS_DH_anon_WITH_DES_CBC_SHA TLS_RSA_WITH_DES_CBC_SHA TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA TLS_RSA_EXPORT_WITH_DES40_CBC_SHA TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 TLS_RSA_EXPORT_WITH_RC4_40_MD5 TLS_EMPTY_RENEGOTIATION_INFO_SCSV compression methods NULL 1 2 0.0217 (0.0002) S>C Alert level fatal value protocol_version 1 3 0.0218 (0.0000) C>S Alert level fatal value protocol_version 1 0.0218 (0.0000) S>C TCP FIN 1 0.0219 (0.0000) C>S TCP RST --- Additional comment from Petr Pisar on 2017-12-04 10:58:52 GMT --- Your problem lies in the perl-LDAP, not in the perl-IO-Socket-SSL. Net::LDAP documentation at start_tls() method reads: sslversion => ’sslv2’ | ’sslv3’ | ’sslv2/3’ | ’tlsv1’ This defines the version of the SSL/TLS protocol to use. Defaults to tlsv1’. And IO::Socket::SSL explains: "’TLSv1’ [...] restrict handshake and protocol to the specified version." Thus your Net::LDAP client forces TLS 1.0 while your server forces TLS 1.1. Therefore the TLS handshake fails. If add some failure checks into your client: #!/usr/bin/perl use strict; use warnings; use diagnostics; use Net::LDAP; my $ldap_master = Net::LDAP->new('localhost', port => '389', version => 3, ); $ldap_master->start_tls() or die "start_tls() failed: $@\n"; my $msg = $ldap_master->search(base => "dc=example,dc=com", filter => "(&(objectclass=posixaccount)(uid=*))", scope => "sub") or die "search() failed: $@\n"; You can see client reports: $ /tmp/test syswrite() on closed filehandle GEN0 at /usr/share/perl5/vendor_perl/Net/LDAP.pm line 806, <DATA> line 522 (#1) (W closed) The filehandle you're writing to got itself closed sometime before now. Check your control flow. and the server reports: 5a252608 connection_get(12) TLS: error: accept - force handshake failure: errno 11 - moznss error -12279 TLS: can't accept: TLS error -12279:Peer using unsupported version of security protocol.. 5a252608 connection_closing: readying conn=1003 sd=12 for close Passing 'sslversion' => 'TLSv1_1' start_tls() helps: ldap_master->start_tls(sslversion => 'TLSv1_1') or die "start_tls() failed: $@\n"; If you want your client to support TLS 1.1 or 1.2, you can use 'TLSv1_1:TLSv1_2'. Or you can disable SSL and keep TLS enabled with 'SSLv23:!SSLv2:!SSLv3'. --------- RHEL-7 (perl-LDAP-0.56-5.el7) is affected. This is a feature request to remove hard-coded default SSL protocol form Net::LDAP Perl module. This was implemented in the upstream in 0.65 version: * LDAP.pm: do not set default sslversion for start_tls() & LDAPS Instead of second-guessing a default sslversion for start_tls() and LDAPS, rely on the - known to be sane - default value used by IO::Socket::SSL.
Also implicit TLS defaults to SSLv23. This does not causes any issues now, but for consistency, it's good to remove the perl-Net-LDAP specific override too.
Created attachment 1362657 [details] 1st upstream fix
Created attachment 1362658 [details] 2nd upstream fix ported to 0.56
How to test: (1) Configure openldap-servers' slapd daemon to use TLS 1.2 only. E.g. add into /etc/openldap/slapd.conf: TLSCACertificatePath /etc/openldap/certs TLSCertificateFile localhost TLSCertificateKeyFile /etc/openldap/certs/password TLSProtocolMin 3.3 and import the certificate and key into slapd's NSS database (it must be readable by ldap group) and start the slapd: # /usr/sbin/slapd -h 'ldap:/// ldaps:/// ldapi:///' -u ldap -d Args,Conns,Config -f /etc/openldap/slapd.conf -F /etc/openldap/slapd.d (2) Run a Net::LDAPS client: $ perl -Ilib -MNet::LDAPS -e 'my $c=Net::LDAPS->new(q{localhost}, version=>3, port =>636) or die qq{$@\n}' Before: It should connect. After: It should still connect. (3) Run a Net::LDAP client with explicit STARTTLS: $ cat /tmp/test #!/usr/bin/perl use strict; use warnings; use diagnostics; use Net::LDAP; my $ldap_master = Net::LDAP->new('localhost', port => '389', version => 3, ); $ldap_master->start_tls() or die "start_tls() failed: $@\n"; my $msg = $ldap_master->search(base => "dc=example,dc=com", filter => "(&(objectclass=posixaccount)(uid=*))", scope => "sub") or die "search() failed: $@\n"; Before: It fails: $ perl /tmp/test syswrite() on closed filehandle GEN0 at /usr/share/perl5/vendor_perl/Net/LDAP.pm line 806, <DATA> line 522 (#1) (W closed) The filehandle you're writing to got itself closed sometime before now. Check your control flow. and the server logs: TLS: error: accept - force handshake failure: errno 11 - moznss error -12279 TLS: can't accept: TLS error -12279:Peer using unsupported version of security protocol.. After: It connects.
Hello, //Business Justification from Customer// 1. Why does the customer need this? (List the business requirements here). We have a very large RHEL6 infrastructure and TLSv 1.0 is no longer acceptable for PCI compliance. 2. Is there already an existing RFE upstream or in Red Hat Bugzilla? NO 3. Does the customer have any specific timeline dependencies? ASAP 4. Is the sales team involved in this request and do they have any additional input? NO 5. List any affected packages or components? As far as I can see through testing it appears perl-LDAP and possibly some versions of openLDAP are both affected. 6. Would the customer be able to assist in testing this functionality if implemented? Absolutely. Thanks Amit
Created attachment 1363575 [details] 2nd upstream fix
Created attachment 1363581 [details] 1st upstream fix ported to 0.56
Created attachment 1363582 [details] 2nd fix ported to 0.56
The test with Net::LDAP client with explicit TLS does not check errors properly. This one should be better: #!/usr/bin/perl use strict; use warnings; use Net::LDAP qw(LDAP_NO_SUCH_OBJECT); my $ldap_master = Net::LDAP->new('localhost', port => '389', version => 3, ); my $retval = $ldap_master->start_tls(); $retval->code and die "start_tls() failed: " . $retval->error; $retval = $ldap_master->search(base => "dc=example,dc=com", filter => "(&(objectclass=posixaccount)(uid=*))", scope => "sub"); $retval->code and $retval->code != LDAP_NO_SUCH_OBJECT and die "search() failed: " . $retval->error; The unpatched build should report the error like this: $ perl test.pl; echo $? start_tls() failed: SSL connect attempt failed because of handshake problems SSL wants a read first at test.pl line 10, <DATA> line 747. 255 Patched build should be silent: $ perl test.pl; echo $? 0
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://access.redhat.com/errata/RHEA-2018:3038