LDAP::SSLConn from ruby fails, probably from not seeing cert

Bug #381791 reported by Xeno Campanoli on 2009-05-29
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
libldap-ruby (Ubuntu)
Undecided
Unassigned

Bug Description

I am unable to execute a simple script to authenticate users using LDAP::SSLConn in Ruby. The following two scripts and output explain the situation:

I have the following working with cleartext LDAP:

#!/usr/bin/ruby
#

require 'ldap'

begin
    ldap_host = 'myldaphost'
    ldap_port = 389
    ldap_conn = LDAP::Conn.new(ldap_host,ldap_port)
    puts "trace 2 ldap_conn: #{ldap_conn.class}"
# ldap_conn.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 )
    puts "trace 3 ldap_conn: #{ldap_conn.class}"
    bind_dn = "uid=#{ARGV[0]},ou=People,ou=Corporate,dc=x,dc=com"
    password_dn = "#{ARGV[1]}"
    ldap_conn.bind(bind_dn,password_dn)
    puts "trace 4 ldap_conn: #{ldap_conn.class}"
rescue
    puts "trace 5 oops"
end

# end of test
----snip---

But when I try to run it with SSL, I get a failure saying "Can't connect LDAP Server". My admin says it is not seeing the certificate. I need to either accept the certificate or turn certification off, but for the life of me I am looking at the rdoc and I cannot find methods for either. Perhaps I just don't understand the vocabulary or something, but I would expect this to be simple. My SSL version is as follows, and gets the diagnosic I gave above:
#!/usr/bin/ruby
#

require 'ldap'

begin
    ldap_host = 'myldaphost'
    ldap_port = 636
    ldap_conn = LDAP::SSLConn.new(ldap_host,ldap_port)
    puts "trace 2 ldap_conn: #{ldap_conn.class}"
    ldap_conn.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 )
    puts "trace 3 ldap_conn: #{ldap_conn.class}"
    bind_dn = "uid=#{ARGV[0]},ou=People,ou=Corporate,dc=x,dc=com"
    password_dn = "#{ARGV[1]}"
    ldap_conn.bind(bind_dn,password_dn)
    puts "trace 4 ldap_conn: #{ldap_conn.class}"
rescue
    puts "trace 5 oops, #{$!}"
end

# end of test
----snip---
Here is the output:
u@h:$ ./t7.rb un 'pw'
trace 2 ldap_conn: LDAP::SSLConn
trace 3 ldap_conn: LDAP::SSLConn
trace 5 oops, Can't contact LDAP server
u@h:$

On the first one, with the proper u/p I get the trace 4. Anyway, please can someone suggest what I may be leaving out, or what is the method for specifying certs or no certs, both would be nice.

I am seeing this behavior on Ubuntu Server installs with the following versions:
Linux hostname.domainstuff 2.6.24-19-server #1 SMP Wed Aug 20 23:54:28 UTC 2008 i686 GNU/Linux
Linux leopard 2.6.28-11-server #42-Ubuntu SMP Fri Apr 17 02:48:10 UTC 2009 i686 GNU/Linux

It appears that the versions of these routines installed on Red Hat and CentOS have a default directory (I believe I was told it was /etc/openldap/cacerts) where you can put certificates that then allow SSL activity with Ruby LDAP, but aparently either we are unable to find that point in Ubuntu Server, or there is no default. Furthermore there is not apparent way to specify it from the application, nor to turn the requirement for the cert off from the API. We also tried running this with the certs in the default directory, and my CentOS pal made it work that way, but on Ubuntu Server it did not work.

Brian Candler (b-candler) wrote :

Have you tried 'apt-get install libopenssl-ruby' ?

Ubuntu separates out all of the openssl-dependent parts of Ruby into a separate package (including things like net/https as well as openssl)

Xeno Campanoli (xeno) wrote :

No. I had not. I just did, however, install it on my test system, and it still gets the same diagnostic:

trace 5 oops, Can't contact LDAP server

I was really hoping when I saw your post that you had found the problem. I wonder if there is some other combination I might have left out. It would be great if this was just a matter of my leaving out a package, or a package omitting a dependency, but people that helped me test this seemed to indicate the certificate was just not being seen. If we could know a place to put the certs where it would be seen that would fix it apparently, as the shell command openssl does the activities properly, and this only fails in the ruby package. However it would also be nice if 1) one could specify a location from the API, 2) one could see clear documentation of the proper location for the cert, 3) one could turn off the cert requirement from the API, and 4) a cert in the same directory as the script programmed was automatically seen for the purposes of testing and simple use. I highly recommen all these 4 items. If I can help I shall. Please someone recommend a next step for me to test or try.

Xeno Campanoli (xeno) wrote :

In case this wasn't clear, the 636 port and ldap server hostname are both used in other combinations elsewhere, so we know these are correct for our testing.

Xeno Campanoli (xeno) wrote :

Can somebody tell me here if this is perhaps intentionally made not to work? I have seen other posts that seem to indicate LDAP::SSLConn has never worked, and perhaps is intended not to work because of the implications for password guessing attacks. Excuse me if I impose my pressure and political beliefs (pointing out that the key is under the front mat) by saying that someone with a little energy could in fact get in and hack this together anyway. Perhaps the real problemthough is with the techno ninnies who in fact don't have enough intellect to do so but have enough to cause stupid amounts of trouble. At any rate, This kind of thing could be very useful, can be done I have determined from a RedHat and CentOS box, and I would think would be something you'd want to be able to do from any server given directions in automation. Perhaps this is just whining, but I think I should be able to do this easily and shops should make security around that fact, and not vice versa.

Xeno Campanoli (xeno) wrote :

Okay, this is probably important to add:

On the Ubuntu server machines I'm using, when I do a plain openssl call like so:

openssl s_client -connect ipaddr:port

where ipaddr and port are definitely correct and shown to work in all other ways with the ldap server we are trying to configure, we get data back with the following ending:

SSL-Session:
    Protocol : TLSv1
    Cipher : RC4-MD5
    Session-ID: 46AEE896A3CB7B0C0044D1169EA9672E769D7BF64194F96D8378D08D750D60AA
    Session-ID-ctx:
    Master-Key: FEADCD684F8CCEEA674C2D725D6BB5E4C1716B877C2B6B176E1C5BD0590D0CDFA28CC93BEB07548C997BD6B2FAB7009F
    Key-Arg : None
    Start Time: 1243885042
    Timeout : 300 (sec)
    Verify return code: 19 (self signed certificate in certificate chain)
---snip---
so a 19, and supposedly we don't have a nice cert. But the cert is there, and when I specify it thus:

openssl s_client -connect ipaddr:port -CAfile $certpath

I get output indicating normal access to our cert:

SSL-Session:
    Protocol : TLSv1
    Cipher : RC4-MD5
    Session-ID: 46AECE8C1C97B9CE8D0547CD2FFF0DB787B11E90A2E4387A430CBEB3996BA67C
    Session-ID-ctx:
    Master-Key: 57B5AD4C296C9B0987539FB728F6ADBC7C6A9C579F0E119E87F7B621769D738053220479ADBA5E811EB163E273D5034E
    Key-Arg : None
    Start Time: 1243888048
    Timeout : 300 (sec)
    Verify return code: 0 (ok)
snip----
so a zero; unixy success. So, it seems to me there is a seriously likely guess to be made here since the responses I got back are similar in wording from openssl and the LDAPpy API to ruby. I hope this helps. xc

Brian Candler (b-candler) wrote :

> someone with a little energy could in fact get in and hack this together anyway

Please feel free to do so:

    apt-get source libldap-ruby1.8

You might try building ruby-ldap from source separately to see if you can get it to behave the way you want, and then see what changes are needed to the deb to match. I notice the changelog in the deb says ssl is supported, but maybe it hasn't been exercised for a while.

However, from a tcpdump you posted on ruby-talk, it looks that SSL *is* being negotiated - certainly the certificate is being sent from the server and there is a further back-and-forth communication before the connection is dropped. This suggests to me that ssl is working fine, but the connection is being dropped later for some other reason - maybe a failure to verify certificate as you suggested, or maybe something else. If you could hack the code to give a better result than just "Can't contact LDAP server" that would be awesome. Maybe just some fprintf(stderr, ...) entries would help pin down your specific problem.

Xeno Campanoli (xeno) wrote :

I just put some trace statements in all the functions with the word 'bind' in them in sslconn.c, and compiling and running that, along with some in the initializer, I show said initializer is called, but none of the 'bind' functions in that file are called. So my guess is the bind method I am using is in the conn.c file only. I don't see a special bind call in the documentation, so I appear to be using the correct ruby to do this. If there is a special sslbind, it is not in the present http://ruby-ldap.sourceforge.net/rdoc. So, I think the critical thing is the ldap software is trying to use the non sslconn bind for the sslconn state.

Xeno Campanoli (xeno) wrote :

Given further traces I installed, it appears I get an exception in the following location right after trace 7a:

fprintf(stderr,"trace 7 rb_ldap_conn_bind_s\n");
  ldapdata->err = ldap_bind_s (ldapdata->ldap, dn, passwd, method);
fprintf(stderr,"trace 7a rb_ldap_conn_bind_s\n");
  Check_LDAP_Result (ldapdata->err);
fprintf(stderr,"trace 7b rb_ldap_conn_bind_s\n");
  ldapdata->bind = 1;

fprintf(stderr,"trace 8 rb_ldap_conn_bind_s\n");
  if (rb_block_given_p ())

Xeno Campanoli (xeno) wrote :

I may misunderstand what is going on with this, but it appears there is no definition of bind specific to my SSL usage inside the sslconn.c source file given the preprocessor define symbol / state I am experiencing of USE_OPENLDAP_SSLCONN, the implication seeming to be that this version of the source file just leaves it, and presumably the internals it needs, out. Perhaps is it intentionally left broken? More likely just doesn't have some recent version of something I will see if I can find it in the version from CentOS or something. I know it works in CentOS. Still open to suggestions here.

Xeno Campanoli (xeno) wrote :

I got some comments that this might have to do with Debian/Ubuntu linking with gnutls instead of openssl by default. I am trying to put together an openssl build right now, but that is being difficult too. Apparently openssl might be less difficult with certain certificates.

Phil Owen (phil-owen) wrote :

I get the same error on my Ubuntu Hardy setup on a slicehost, however I know the gem works because when I run the exact same rails app on my local development server, it works perfectly.

I realize it's been over a year since the last comment, but PLEASE let me know if you found/find a way to get this working!

Changed in libldap-ruby (Ubuntu):
status: New → Confirmed
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers