From d1cf134ba98dd0c0c4565e090221b15b207e265e Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Tue, 6 May 2014 11:36:02 -0700 Subject: [PATCH 1/2] Enable verifing the TLS connection in start_tls Rather than just blindly OpenSSL::SSL::VERIFY_NONE-ing, verify the peer if we're given a PEM formatted cafile. --- lib/net/ldap.rb | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index be21c1ef..e100c23f 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -1160,9 +1160,19 @@ def getbyte end end - def self.wrap_with_ssl(io) + def self.wrap_with_ssl(io,*args) + raise Net::LDAP::LdapError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL ctx = OpenSSL::SSL::SSLContext.new + # If we've been given a cafile in the arguments hash, then we want to + # actually verify the TLS connection rather than just the default of + # NO_VERIFY. + if args.last.instance_of?(Hash) && args.last.has_key?(:cafile) + cafile = args.last[:cafile] + ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER + raise "CA file '#{cafile}' doesn't exist" unless File.exists? cafile + ctx.ca_file = cafile + end conn = OpenSSL::SSL::SSLSocket.new(io, ctx) conn.connect conn.sync_close = true @@ -1213,8 +1223,11 @@ def setup_encryption(args) raise Net::LDAP::LdapError, "no start_tls result" if be.nil? pdu = Net::LDAP::PDU.new(be) raise Net::LDAP::LdapError, "no start_tls result" if pdu.nil? + + a = { :cafile => args[:cafile] } if args[:cafile] + if pdu.result_code.zero? - @conn = self.class.wrap_with_ssl(@conn) + @conn = self.class.wrap_with_ssl(@conn,a) else raise Net::LDAP::LdapError, "start_tls failed: #{pdu.result_code}" end From 80448447772bb29935a303d63e3bc58795638aaf Mon Sep 17 00:00:00 2001 From: Ben Hughes Date: Tue, 6 May 2014 12:24:13 -0700 Subject: [PATCH 2/2] Update documentation on start_tls method. Explain using the start_tls method and the additions for SSL peer verification. --- lib/net/ldap.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb index e100c23f..4b42a83d 100644 --- a/lib/net/ldap.rb +++ b/lib/net/ldap.rb @@ -456,9 +456,8 @@ def authenticate(username, password) # additional capabilities are added, more configuration values will be # added here. # - # Currently, the only supported argument is { :method => :simple_tls }. - # (Equivalently, you may pass the symbol :simple_tls all by itself, - # without enclosing it in a Hash.) + # The supported methods are { :method => :simple_tls } and { :method => + # :start_tls }. # # The :simple_tls encryption method encrypts all communications # with the LDAP server. It completely establishes SSL/TLS encryption with @@ -479,9 +478,13 @@ def authenticate(username, password) # standard port for simple-TLS encrypted connections is 636. Be sure you # are using the correct port. # - # [Note: a future version of Net::LDAP will support the STARTTLS LDAP - # control, which will enable encrypted communications on the same TCP port - # used for unencrypted connections.] + # Using :start_tls you are able to verify the peer in the TLS + # negotiation. To verify the peer, you can add the :cafile element + # with the path to a file containing one or more valid PEM formatted + # CA certificates. For example: + # { :method => :start_tls, :cafile => '/etc/ssl/cafile.pem' } + # Net::Ldap will raise an exception if the CA file doesn't exist, or if + # the peer fails TLS verification. def encryption(args) case args when :simple_tls, :start_tls