Skip to content

Commit 074a408

Browse files
committed
support a connection callback for proxies
also refactors connection establishment to only go through one method
1 parent fd2d1ed commit 074a408

File tree

4 files changed

+68
-94
lines changed

4 files changed

+68
-94
lines changed

Contributors.rdoc

+1
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ Contributions since:
2020
* Erik Hetzner (egh)
2121
* nowhereman
2222
* David J. Lee (DavidJLee)
23+
* Cody Cutrer (ccutrer)

History.rdoc

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
=== Net::LDAP next
2+
* Minor enhancements:
3+
* Add support for a connection callback, to allow proxies to be used
4+
15
=== Net::LDAP 0.10.1
26
* Bug fixes:
37
* Fix Integer BER encoding of signed values

lib/net/ldap.rb

+45-94
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,10 @@ def self.result2string(code) #:nodoc:
441441
# described below. The following arguments are supported:
442442
# * :host => the LDAP server's IP-address (default 127.0.0.1)
443443
# * :port => the LDAP server's TCP port (default 389)
444+
# * :connect_cb => a Proc that will be called when a new connection is
445+
# needed. This should return an actual Ruby IO object. Useful for
446+
# manually handling connecting, like if you want to go through a proxy
447+
# server. It will receive :host: and :port: as arguments.
444448
# * :auth => a Hash containing authorization parameters. Currently
445449
# supported values include: {:method => :anonymous} and {:method =>
446450
# :simple, :username => your_user_name, :password => your_password }
@@ -469,6 +473,7 @@ def self.result2string(code) #:nodoc:
469473
def initialize(args = {})
470474
@host = args[:host] || DefaultHost
471475
@port = args[:port] || DefaultPort
476+
@connect_cb = args[:connect_cb]
472477
@verbose = false # Make this configurable with a switch on the class.
473478
@auth = args[:auth] || DefaultAuth
474479
@base = args[:base] || DefaultTreebase
@@ -670,12 +675,7 @@ def open
670675

671676
instrument "open.net_ldap" do |payload|
672677
begin
673-
@open_connection =
674-
Net::LDAP::Connection.new \
675-
:host => @host,
676-
:port => @port,
677-
:encryption => @encryption,
678-
:instrumentation_service => @instrumentation_service
678+
@open_connection = new_connection
679679
payload[:connection] = @open_connection
680680
payload[:bind] = @open_connection.bind(@auth)
681681
yield self
@@ -745,27 +745,11 @@ def search(args = {})
745745
result_set = return_result_set ? [] : nil
746746

747747
instrument "search.net_ldap", args do |payload|
748-
if @open_connection
749-
@result = @open_connection.search(args) { |entry|
748+
use_connection(args[:auth]) do |conn|
749+
@result = conn.search(args) { |entry|
750750
result_set << entry if result_set
751751
yield entry if block_given?
752752
}
753-
else
754-
begin
755-
conn = Net::LDAP::Connection.new \
756-
:host => @host,
757-
:port => @port,
758-
:encryption => @encryption,
759-
:instrumentation_service => @instrumentation_service
760-
if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess
761-
@result = conn.search(args) { |entry|
762-
result_set << entry if result_set
763-
yield entry if block_given?
764-
}
765-
end
766-
ensure
767-
conn.close if conn
768-
end
769753
end
770754

771755
if return_result_set
@@ -844,11 +828,7 @@ def bind(auth = @auth)
844828
payload[:bind] = @result = @open_connection.bind(auth)
845829
else
846830
begin
847-
conn = Connection.new \
848-
:host => @host,
849-
:port => @port,
850-
:encryption => @encryption,
851-
:instrumentation_service => @instrumentation_service
831+
conn = new_connection
852832
payload[:connection] = conn
853833
payload[:bind] = @result = conn.bind(auth)
854834
ensure
@@ -946,22 +926,8 @@ def bind_as(args = {})
946926
# end
947927
def add(args)
948928
instrument "add.net_ldap", args do |payload|
949-
if @open_connection
950-
@result = @open_connection.add(args)
951-
else
952-
@result = 0
953-
begin
954-
conn = Connection.new \
955-
:host => @host,
956-
:port => @port,
957-
:encryption => @encryption,
958-
:instrumentation_service => @instrumentation_service
959-
if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess
960-
@result = conn.add(args)
961-
end
962-
ensure
963-
conn.close if conn
964-
end
929+
use_connection(args[:auth]) do |conn|
930+
@result = conn.add(args)
965931
end
966932
@result.success?
967933
end
@@ -1050,24 +1016,9 @@ def add(args)
10501016
# does _not_ imply transactional atomicity, which LDAP does not provide.
10511017
def modify(args)
10521018
instrument "modify.net_ldap", args do |payload|
1053-
if @open_connection
1054-
@result = @open_connection.modify(args)
1055-
else
1056-
@result = 0
1057-
begin
1058-
conn = Connection.new \
1059-
:host => @host,
1060-
:port => @port,
1061-
:encryption => @encryption,
1062-
:instrumentation_service => @instrumentation_service
1063-
if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess
1064-
@result = conn.modify(args)
1065-
end
1066-
ensure
1067-
conn.close if conn
1068-
end
1019+
use_connection(args[:auth]) do |conn|
1020+
@result = conn.modify(args)
10691021
end
1070-
10711022
@result.success?
10721023
end
10731024
end
@@ -1127,22 +1078,8 @@ def delete_attribute(dn, attribute)
11271078
# _Documentation_ _stub_
11281079
def rename(args)
11291080
instrument "rename.net_ldap", args do |payload|
1130-
if @open_connection
1131-
@result = @open_connection.rename(args)
1132-
else
1133-
@result = 0
1134-
begin
1135-
conn = Connection.new \
1136-
:host => @host,
1137-
:port => @port,
1138-
:encryption => @encryption,
1139-
:instrumentation_service => @instrumentation_service
1140-
if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess
1141-
@result = conn.rename(args)
1142-
end
1143-
ensure
1144-
conn.close if conn
1145-
end
1081+
use_connection(args[:auth]) do |conn|
1082+
@result = conn.rename(args)
11461083
end
11471084
@result.success?
11481085
end
@@ -1160,22 +1097,8 @@ def rename(args)
11601097
# ldap.delete :dn => dn
11611098
def delete(args)
11621099
instrument "delete.net_ldap", args do |payload|
1163-
if @open_connection
1164-
@result = @open_connection.delete(args)
1165-
else
1166-
@result = 0
1167-
begin
1168-
conn = Connection.new \
1169-
:host => @host,
1170-
:port => @port,
1171-
:encryption => @encryption,
1172-
:instrumentation_service => @instrumentation_service
1173-
if (@result = conn.bind(args[:auth] || @auth)).result_code == Net::LDAP::ResultCodeSuccess
1174-
@result = conn.delete(args)
1175-
end
1176-
ensure
1177-
conn.close
1178-
end
1100+
use_connection(args[:auth]) do |conn|
1101+
@result = conn.delete(args)
11791102
end
11801103
@result.success?
11811104
end
@@ -1277,4 +1200,32 @@ def paged_searches_supported?
12771200
@server_caps ||= search_root_dse
12781201
@server_caps[:supportedcontrol].include?(Net::LDAP::LDAPControls::PAGED_RESULTS)
12791202
end
1203+
1204+
private
1205+
1206+
def use_connection(auth)
1207+
if @open_connection
1208+
yield @open_connection
1209+
else
1210+
@result = 0
1211+
begin
1212+
conn = new_connection
1213+
if (@result = conn.bind(auth || @auth)).result_code == Net::LDAP::ResultCodeSuccess
1214+
yield conn
1215+
end
1216+
ensure
1217+
conn.close if conn
1218+
end
1219+
end
1220+
end
1221+
1222+
def new_connection
1223+
socket = @connect_cb.call(@host, @port) if @connect_cb
1224+
Net::LDAP::Connection.new \
1225+
:socket => socket,
1226+
:host => @host,
1227+
:port => @port,
1228+
:encryption => @encryption,
1229+
:instrumentation_service => @instrumentation_service
1230+
end
12801231
end # class LDAP

test/test_ldap.rb

+18
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,22 @@ def test_instrument_search_with_size
5757
assert_equal "(uid=user1)", payload[:filter]
5858
assert_equal result.size, payload[:size]
5959
end
60+
61+
def test_connect_cb
62+
flexmock(Net::LDAP::Connection).should_receive(:new).with(
63+
:socket => 42,
64+
:host => "test.mocked.com",
65+
:port => 636,
66+
:encryption => nil,
67+
:instrumentation_service => @service).and_return(@connection)
68+
flexmock(@connection).should_receive(:bind).and_return(flexmock(:bind_result, :result_code => Net::LDAP::ResultCodeSuccess))
69+
70+
@subject = Net::LDAP.new \
71+
:connect_cb => lambda { |host, port| 42 },
72+
:host => "test.mocked.com", :port => 636,
73+
:force_no_page => true, # so server capabilities are not queried
74+
:instrumentation_service => @service
75+
76+
@subject.open {}
77+
end
6078
end

0 commit comments

Comments
 (0)