Ruby verify the certificate of secure ldap server

3.2k views Asked by At

I am using https://github.com/ruby-ldap/ruby-net-ldap (net-ldap) gem to verify the authenticity of a user in my rails app. But before passing data to the ldap server, I need to verify that I am talking with the same secure server. Is there a workaround which allows me to verify the certificate in ruby

Additional details: (things I have tried)

  1. The certificate which is passed on to me is same as the one I see when I run

    openssl s_client -showcerts -connect "<host>:<port>" </dev/null 2>/dev/null|openssl x509 -outform PEM
    
  2. I used http://www.ldapsoft.com/ to connect to client's server Unless I add the certificate file given to me in Security > Manage server certificates, I get a warning saying unknown security certificate

  3. I tried do it manually first in plain ruby (without gem) But i get following error

    test-ssl.rb:23:in `connect': SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (OpenSSL::SSL::SSLError)
    

    Code:

    cert_store = OpenSSL::X509::Store.new
    cert_store.add_file "server-wildcard.crt"
    io = TCPSocket.new("SECURELDAP.MYSITE.EDU","636")
    ctx = OpenSSL::SSL::SSLContext.new
    #ctx.cert = OpenSSL::X509::Certificate.new(File.read("server-wildcard.crt"))
    #ctx.client_ca = OpenSSL::X509::Certificate.new(File.read("server-wildcard.crt"))
    #ctx.ca_file = "server-wildcard.crt"
    #ctx.ca_path = "./"
    ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT
    ctx.cert_store = cert_store
    conn = OpenSSL::SSL::SSLSocket.new(io, ctx)
    conn.connect
    
2

There are 2 answers

0
Charles Duffy On

As of today (late 2016), ruby-net-ldap supports this upstream! However, tls_options needs to be passed with verify_mode set to a value other than the default VERIFY_NONE.

# optional: create/pass your own cert_store
cert_store = OpenSSL::X509::Store.new
cert_store.set_default_paths # or add your own CAdir, &c.

# attributes documented for OpenSSL::SSL::SSLContext are valid here
tls_options = {
  verify_mode: OpenSSL::SSL::VERIFY_PEER
  cert_store: cert_store
}

ldap = Net::LDAP.new(
  :host => host,
  :port => port,
  :encryption => {
    :method => :simple_tls, # could also be :start_tls
    :tls_options => tls_options
  }
)
0
mintuhouse On

I am posting my solution here for the sake of completeness.

net-ldap gem override to support certificate validation https://gist.github.com/mintuhouse/9931865

Ideal Solution:
Maintain list of trusted root CAs on your server (If you are lazy like me, have a cron job which will download (weekly maintained by curl) copy from http://curl.haxx.se/ca/cacert.pem)
Override Net::HTTP to always use this trusted certificate list