Skip to content

Commit 22fa81c

Browse files
committed
use connect_timeout when establishing an openssl connection
1 parent 3bf849d commit 22fa81c

File tree

1 file changed

+25
-9
lines changed

1 file changed

+25
-9
lines changed

lib/net/ldap/connection.rb

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,27 @@ def socket_class=(socket_class)
3131
@socket_class = socket_class
3232
end
3333

34-
def prepare_socket(server)
34+
def prepare_socket(server, timeout)
3535
socket = server[:socket]
3636
encryption = server[:encryption]
3737

3838
@conn = socket
39-
setup_encryption encryption if encryption
39+
setup_encryption(encryption, timeout) if encryption
4040
end
4141

4242
def open_connection(server)
4343
hosts = server[:hosts]
4444
encryption = server[:encryption]
4545

46+
timeout = server[:connect_timeout] || DefaultConnectTimeout
4647
socket_opts = {
47-
connect_timeout: server[:connect_timeout] || DefaultConnectTimeout,
48+
connect_timeout: timeout,
4849
}
4950

5051
errors = []
5152
hosts.each do |host, port|
5253
begin
53-
prepare_socket(server.merge(socket: @socket_class.new(host, port, socket_opts)))
54+
prepare_socket(server.merge(socket: @socket_class.new(host, port, socket_opts)), timeout)
5455
return
5556
rescue Net::LDAP::Error, SocketError, SystemCallError,
5657
OpenSSL::SSL::SSLError => e
@@ -76,7 +77,7 @@ def close
7677
end
7778
end
7879

79-
def self.wrap_with_ssl(io, tls_options = {})
80+
def self.wrap_with_ssl(io, tls_options = {}, timeout=nil)
8081
raise Net::LDAP::NoOpenSSLError, "OpenSSL is unavailable" unless Net::LDAP::HasOpenSSL
8182

8283
ctx = OpenSSL::SSL::SSLContext.new
@@ -86,7 +87,22 @@ def self.wrap_with_ssl(io, tls_options = {})
8687
ctx.set_params(tls_options) unless tls_options.empty?
8788

8889
conn = OpenSSL::SSL::SSLSocket.new(io, ctx)
89-
conn.connect
90+
91+
begin
92+
conn.connect_nonblock
93+
rescue IO::WaitReadable
94+
if IO.select([conn], nil, nil, timeout)
95+
retry
96+
else
97+
raise Net::LDAP::LdapError, "OpenSSL connection read timeout"
98+
end
99+
rescue IO::WaitWritable
100+
if IO.select(nil, [conn], nil, timeout)
101+
retry
102+
else
103+
raise Net::LDAP::LdapError, "OpenSSL connection write timeout"
104+
end
105+
end
90106

91107
# Doesn't work:
92108
# conn.sync_close = true
@@ -123,11 +139,11 @@ def self.wrap_with_ssl(io, tls_options = {})
123139
# communications, as with simple_tls. Thanks for Kouhei Sutou for
124140
# generously contributing the :start_tls path.
125141
#++
126-
def setup_encryption(args)
142+
def setup_encryption(args, timeout)
127143
args[:tls_options] ||= {}
128144
case args[:method]
129145
when :simple_tls
130-
@conn = self.class.wrap_with_ssl(@conn, args[:tls_options])
146+
@conn = self.class.wrap_with_ssl(@conn, args[:tls_options], timeout)
131147
# additional branches requiring server validation and peer certs, etc.
132148
# go here.
133149
when :start_tls
@@ -144,7 +160,7 @@ def setup_encryption(args)
144160
end
145161

146162
if pdu.result_code.zero?
147-
@conn = self.class.wrap_with_ssl(@conn, args[:tls_options])
163+
@conn = self.class.wrap_with_ssl(@conn, args[:tls_options], timeout)
148164
else
149165
raise Net::LDAP::StartTLSError, "start_tls failed: #{pdu.result_code}"
150166
end

0 commit comments

Comments
 (0)