Skip to content

Commit d7d2c52

Browse files
committed
Implement custom tls options
This allows users of the API to either specify a simple CA-File for certificate verification, or a custom SSLContext in order for a more fine-grained control of the TLS options they want to use. As of now, no additional tests were added, but the existing tests were changed to reflect the changes in internal methods, so that they can still pass
1 parent fc38d1c commit d7d2c52

File tree

3 files changed

+27
-9
lines changed

3 files changed

+27
-9
lines changed

lib/net/ldap.rb

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -537,10 +537,6 @@ def authenticate(username, password)
537537
# additional capabilities are added, more configuration values will be
538538
# added here.
539539
#
540-
# Currently, the only supported argument is { :method => :simple_tls }.
541-
# (Equivalently, you may pass the symbol :simple_tls all by itself,
542-
# without enclosing it in a Hash.)
543-
#
544540
# The :simple_tls encryption method encrypts <i>all</i> communications
545541
# with the LDAP server. It completely establishes SSL/TLS encryption with
546542
# the LDAP server before any LDAP-protocol data is exchanged. There is no
@@ -563,6 +559,17 @@ def authenticate(username, password)
563559
# The :start_tls like the :simple_tls encryption method also encrypts all
564560
# communcations with the LDAP server. With the exception that it operates
565561
# over the standard TCP port.
562+
#
563+
# In order to allow verification of server certificates and other TLS-related
564+
# options, the keys :cafile and :ssl_context can be used.
565+
#
566+
# The :cafile option is a single filename that points to one or more
567+
# PEM-encoded certificates. These certificates are used as a certificate auhority
568+
# to verify the server certificates.
569+
#
570+
# For fine-grained control of the TLS settings, it is also possible to use the
571+
# :ssl_context option to pass a custom OpenSSL::SSL::SSLContext. Consult the
572+
# OpenSSL documentation for more information on the available options.
566573
def encryption(args)
567574
case args
568575
when :simple_tls, :start_tls

lib/net/ldap/connection.rb

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,20 @@ def close
4141
end
4242
end
4343

44-
def self.wrap_with_ssl(io)
44+
def self.wrap_with_ssl(io, ssl_context = nil, cafile = nil)
4545
raise Net::LDAP::LdapError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL
46-
ctx = OpenSSL::SSL::SSLContext.new
46+
if (ssl_context && cafile)
47+
raise Net::LDAP::LdapError, "Please specify only one of ssl_context or cafile"
48+
end
49+
50+
ctx = ssl_context ? ssl_context : OpenSSL::SSL::SSLContext.new
51+
52+
# OpenSSL automatically merges the given parameters with the default parameters
53+
# These include verification and some common workarounds
54+
if cafile
55+
ctx.set_params({:ca_file => cafile})
56+
end
57+
4758
conn = OpenSSL::SSL::SSLSocket.new(io, ctx)
4859
conn.connect
4960

@@ -85,7 +96,7 @@ def self.wrap_with_ssl(io)
8596
def setup_encryption(args)
8697
case args[:method]
8798
when :simple_tls
88-
@conn = self.class.wrap_with_ssl(@conn)
99+
@conn = self.class.wrap_with_ssl(@conn, args[:ssl_context], args[:cafile])
89100
# additional branches requiring server validation and peer certs, etc.
90101
# go here.
91102
when :start_tls
@@ -102,7 +113,7 @@ def setup_encryption(args)
102113
end
103114

104115
if pdu.result_code.zero?
105-
@conn = self.class.wrap_with_ssl(@conn)
116+
@conn = self.class.wrap_with_ssl(@conn, args[:ssl_context], args[:cafile])
106117
else
107118
raise Net::LDAP::LdapError, "start_tls failed: #{pdu.result_code}"
108119
end

test/test_ldap_connection.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ def test_queued_read_setup_encryption_with_start_tls
202202
and_return(result2)
203203
mock.should_receive(:write)
204204
conn = Net::LDAP::Connection.new(:socket => mock)
205-
flexmock(Net::LDAP::Connection).should_receive(:wrap_with_ssl).with(mock).
205+
flexmock(Net::LDAP::Connection).should_receive(:wrap_with_ssl).with(mock, nil, nil).
206206
and_return(mock)
207207

208208
conn.next_msgid # simulates ongoing query

0 commit comments

Comments
 (0)