Skip to content

Commit 4c1f95a

Browse files
author
Jerry Cheung
committed
Merge remote-tracking branch 'origin/master' into search-timeout
Conflicts: lib/net/ldap/connection.rb
2 parents 4597aad + ea124f2 commit 4c1f95a

File tree

3 files changed

+65
-42
lines changed

3 files changed

+65
-42
lines changed

lib/net/ldap/connection.rb

Lines changed: 60 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -311,26 +311,47 @@ def encode_sort_controls(sort_definitions)
311311
# type-5 packet, which might never come. We need to support the time-limit
312312
# in the protocol.
313313
#++
314-
def search(args = {})
315-
search_filter = (args && args[:filter]) ||
316-
Net::LDAP::Filter.eq("objectclass", "*")
317-
search_filter = Net::LDAP::Filter.construct(search_filter) if search_filter.is_a?(String)
318-
search_base = (args && args[:base]) || "dc=example, dc=com"
319-
search_attributes = ((args && args[:attributes]) || []).map { |attr| attr.to_s.to_ber}
320-
return_referrals = args && args[:return_referrals] == true
321-
sizelimit = (args && args[:size].to_i) || 0
322-
timelimit = (args && args[:time].to_i) || 0
323-
raise Net::LDAP::LdapError, "invalid search-size" unless sizelimit >= 0
324-
paged_searches_supported = (args && args[:paged_searches_supported])
325-
326-
attributes_only = (args and args[:attributes_only] == true)
327-
scope = args[:scope] || Net::LDAP::SearchScope_WholeSubtree
314+
def search(args = nil)
315+
args ||= {}
316+
317+
# filtering, scoping, search base
318+
# filter: https://tools.ietf.org/html/rfc4511#section-4.5.1.7
319+
# base: https://tools.ietf.org/html/rfc4511#section-4.5.1.1
320+
# scope: https://tools.ietf.org/html/rfc4511#section-4.5.1.2
321+
filter = args[:filter] || Net::LDAP::Filter.eq("objectClass", "*")
322+
base = args[:base]
323+
scope = args[:scope] || Net::LDAP::SearchScope_WholeSubtree
324+
325+
# attr handling
326+
# attrs: https://tools.ietf.org/html/rfc4511#section-4.5.1.8
327+
# attrs_only: https://tools.ietf.org/html/rfc4511#section-4.5.1.6
328+
attrs = Array(args[:attributes])
329+
attrs_only = args[:attributes_only] == true
330+
331+
# references
332+
# refs: https://tools.ietf.org/html/rfc4511#section-4.5.3
333+
# deref: https://tools.ietf.org/html/rfc4511#section-4.5.1.3
334+
refs = args[:return_referrals] == true
335+
deref = args[:deref] || Net::LDAP::DerefAliases_Never
336+
337+
# limiting, paging, sorting
338+
# size: https://tools.ietf.org/html/rfc4511#section-4.5.1.4
339+
# time: https://tools.ietf.org/html/rfc4511#section-4.5.1.5
340+
size = args[:size].to_i
341+
time = args[:time].to_i
342+
paged = args[:paged_searches_supported]
343+
sort = args.fetch(:sort_controls, false)
344+
345+
# arg validation
346+
raise Net::LDAP::LdapError, "search base is required" unless base
347+
raise Net::LDAP::LdapError, "invalid search-size" unless size >= 0
328348
raise Net::LDAP::LdapError, "invalid search scope" unless Net::LDAP::SearchScopes.include?(scope)
349+
raise Net::LDAP::LdapError, "invalid alias dereferencing value" unless Net::LDAP::DerefAliasesArray.include?(deref)
329350

330-
sort_control = encode_sort_controls(args.fetch(:sort_controls){ false })
331-
332-
deref = args[:deref] || Net::LDAP::DerefAliases_Never
333-
raise Net::LDAP::LdapError.new( "invalid alias dereferencing value" ) unless Net::LDAP::DerefAliasesArray.include?(deref)
351+
# arg transforms
352+
filter = Net::LDAP::Filter.construct(filter) if filter.is_a?(String)
353+
ber_attrs = attrs.map { |attr| attr.to_s.to_ber }
354+
ber_sort = encode_sort_controls(sort)
334355

335356
# An interesting value for the size limit would be close to A/D's
336357
# built-in page limit of 1000 records, but openLDAP newer than version
@@ -357,36 +378,36 @@ def search(args = {})
357378
n_results = 0
358379

359380
instrument "search.net_ldap_connection",
360-
:filter => search_filter,
361-
:base => search_base,
362-
:scope => scope,
363-
:limit => sizelimit,
364-
:timelimit => timelimit,
365-
:sort => sort_control,
366-
:referrals => return_referrals,
367-
:deref => deref,
368-
:attributes => search_attributes do |payload|
381+
filter: filter,
382+
base: base,
383+
scope: scope,
384+
limit: size,
385+
time: time,
386+
sort: sort,
387+
referrals: refs,
388+
deref: deref,
389+
attributes: attrs do |payload|
369390
loop do
370391
# should collect this into a private helper to clarify the structure
371392
query_limit = 0
372-
if sizelimit > 0
373-
if paged_searches_supported
374-
query_limit = (((sizelimit - n_results) < 126) ? (sizelimit -
393+
if size > 0
394+
if paged
395+
query_limit = (((size - n_results) < 126) ? (size -
375396
n_results) : 0)
376397
else
377-
query_limit = sizelimit
398+
query_limit = size
378399
end
379400
end
380401

381402
request = [
382-
search_base.to_ber,
403+
base.to_ber,
383404
scope.to_ber_enumerated,
384405
deref.to_ber_enumerated,
385406
query_limit.to_ber, # size limit
386407
timelimit.to_ber,
387-
attributes_only.to_ber,
388-
search_filter.to_ber,
389-
search_attributes.to_ber_sequence
408+
attrs_only.to_ber,
409+
filter.to_ber,
410+
ber_attrs.to_ber_sequence
390411
].to_ber_appsequence(3)
391412

392413
# rfc2696_cookie sometimes contains binary data from Microsoft Active Directory
@@ -400,8 +421,8 @@ def search(args = {})
400421
# Criticality MUST be false to interoperate with normal LDAPs.
401422
false.to_ber,
402423
rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber
403-
].to_ber_sequence if paged_searches_supported
404-
controls << sort_control if sort_control
424+
].to_ber_sequence if paged
425+
controls << ber_sort if ber_sort
405426
controls = controls.empty? ? nil : controls.to_ber_contextspecific(0)
406427

407428
write(request, controls)
@@ -415,7 +436,7 @@ def search(args = {})
415436
n_results += 1
416437
yield pdu.search_entry if block_given?
417438
when Net::LDAP::PDU::SearchResultReferral
418-
if return_referrals
439+
if refs
419440
if block_given?
420441
se = Net::LDAP::Entry.new
421442
se[:search_referrals] = (pdu.search_referrals || [])
@@ -425,7 +446,7 @@ def search(args = {})
425446
when Net::LDAP::PDU::SearchResult
426447
result_pdu = pdu
427448
controls = pdu.result_controls
428-
if return_referrals && pdu.result_code == 10
449+
if refs && pdu.result_code == 10
429450
if block_given?
430451
se = Net::LDAP::Entry.new
431452
se[:search_referrals] = (pdu.search_referrals || [])

test/integration/test_delete.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ def setup
1414
sn: "delete-user1",
1515
1616
}
17-
assert @ldap.add(dn: @dn, attributes: attrs), @ldap.get_operation_result.inspect
17+
unless @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject)
18+
assert @ldap.add(dn: @dn, attributes: attrs), @ldap.get_operation_result.inspect
19+
end
1820
assert @ldap.search(base: @dn, scope: Net::LDAP::SearchScope_BaseObject)
1921
end
2022

test/test_ldap_connection.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ def test_bind_net_ldap_connection_event
186186
def test_search_net_ldap_connection_event
187187
# search data
188188
search_data_ber = Net::BER::BerIdentifiedArray.new([2, [
189-
"uid=user1,ou=OrgUnit2,ou=OrgUnitTop,dc=openldap,dc=ghe,dc=local",
189+
"uid=user1,ou=People,dc=rubyldap,dc=com",
190190
[ ["uid", ["user1"]] ]
191191
]])
192192
search_data_ber.ber_identifier = Net::LDAP::PDU::SearchReturnedData
@@ -200,7 +200,7 @@ def test_search_net_ldap_connection_event
200200

201201
events = @service.subscribe "search.net_ldap_connection"
202202

203-
result = @connection.search(filter: "(uid=user1)")
203+
result = @connection.search(filter: "(uid=user1)", base: "ou=People,dc=rubyldap,dc=com")
204204
assert result.success?, "should be success"
205205

206206
# a search event

0 commit comments

Comments
 (0)