Skip to content

Commit 4435022

Browse files
committed
Instrument Net::LDAP::Connection#search
1 parent 12ae55b commit 4435022

File tree

1 file changed

+106
-90
lines changed

1 file changed

+106
-90
lines changed

lib/net/ldap.rb

Lines changed: 106 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,108 +1488,124 @@ def search(args = {})
14881488
result_pdu = nil
14891489
n_results = 0
14901490

1491-
loop {
1492-
# should collect this into a private helper to clarify the structure
1493-
query_limit = 0
1494-
if sizelimit > 0
1495-
if paged_searches_supported
1496-
query_limit = (((sizelimit - n_results) < 126) ? (sizelimit -
1497-
n_results) : 0)
1498-
else
1499-
query_limit = sizelimit
1491+
instrument "search.net_ldap_connection",
1492+
:filter => search_filter,
1493+
:base => search_base,
1494+
:scope => scope,
1495+
:limit => sizelimit,
1496+
:sort => sort_control,
1497+
:referrals => return_referrals,
1498+
:deref => deref,
1499+
:attributes => search_attributes do |payload|
1500+
loop do
1501+
# should collect this into a private helper to clarify the structure
1502+
query_limit = 0
1503+
if sizelimit > 0
1504+
if paged_searches_supported
1505+
query_limit = (((sizelimit - n_results) < 126) ? (sizelimit -
1506+
n_results) : 0)
1507+
else
1508+
query_limit = sizelimit
1509+
end
15001510
end
1501-
end
15021511

1503-
request = [
1504-
search_base.to_ber,
1505-
scope.to_ber_enumerated,
1506-
deref.to_ber_enumerated,
1507-
query_limit.to_ber, # size limit
1508-
0.to_ber,
1509-
attributes_only.to_ber,
1510-
search_filter.to_ber,
1511-
search_attributes.to_ber_sequence
1512-
].to_ber_appsequence(3)
1513-
1514-
# rfc2696_cookie sometimes contains binary data from Microsoft Active Directory
1515-
# this breaks when calling to_ber. (Can't force binary data to UTF-8)
1516-
# we have to disable paging (even though server supports it) to get around this...
1517-
1518-
controls = []
1519-
controls <<
1520-
[
1521-
Net::LDAP::LDAPControls::PAGED_RESULTS.to_ber,
1522-
# Criticality MUST be false to interoperate with normal LDAPs.
1523-
false.to_ber,
1524-
rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber
1525-
].to_ber_sequence if paged_searches_supported
1526-
controls << sort_control if sort_control
1527-
controls = controls.empty? ? nil : controls.to_ber_contextspecific(0)
1528-
1529-
pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence
1530-
write pkt
1531-
1532-
result_pdu = nil
1533-
controls = []
1534-
1535-
while (be = read) && (pdu = Net::LDAP::PDU.new(be))
1536-
case pdu.app_tag
1537-
when 4 # search-data
1538-
n_results += 1
1539-
yield pdu.search_entry if block_given?
1540-
when 19 # search-referral
1541-
if return_referrals
1542-
if block_given?
1543-
se = Net::LDAP::Entry.new
1544-
se[:search_referrals] = (pdu.search_referrals || [])
1545-
yield se
1512+
request = [
1513+
search_base.to_ber,
1514+
scope.to_ber_enumerated,
1515+
deref.to_ber_enumerated,
1516+
query_limit.to_ber, # size limit
1517+
0.to_ber,
1518+
attributes_only.to_ber,
1519+
search_filter.to_ber,
1520+
search_attributes.to_ber_sequence
1521+
].to_ber_appsequence(3)
1522+
1523+
# rfc2696_cookie sometimes contains binary data from Microsoft Active Directory
1524+
# this breaks when calling to_ber. (Can't force binary data to UTF-8)
1525+
# we have to disable paging (even though server supports it) to get around this...
1526+
1527+
controls = []
1528+
controls <<
1529+
[
1530+
Net::LDAP::LDAPControls::PAGED_RESULTS.to_ber,
1531+
# Criticality MUST be false to interoperate with normal LDAPs.
1532+
false.to_ber,
1533+
rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber
1534+
].to_ber_sequence if paged_searches_supported
1535+
controls << sort_control if sort_control
1536+
controls = controls.empty? ? nil : controls.to_ber_contextspecific(0)
1537+
1538+
pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence
1539+
write pkt
1540+
1541+
result_pdu = nil
1542+
controls = []
1543+
1544+
while (be = read) && (pdu = Net::LDAP::PDU.new(be))
1545+
case pdu.app_tag
1546+
when 4 # search-data
1547+
n_results += 1
1548+
yield pdu.search_entry if block_given?
1549+
when 19 # search-referral
1550+
if return_referrals
1551+
if block_given?
1552+
se = Net::LDAP::Entry.new
1553+
se[:search_referrals] = (pdu.search_referrals || [])
1554+
yield se
1555+
end
15461556
end
1547-
end
1548-
when 5 # search-result
1549-
result_pdu = pdu
1550-
controls = pdu.result_controls
1551-
if return_referrals && pdu.result_code == 10
1552-
if block_given?
1553-
se = Net::LDAP::Entry.new
1554-
se[:search_referrals] = (pdu.search_referrals || [])
1555-
yield se
1557+
when 5 # search-result
1558+
result_pdu = pdu
1559+
controls = pdu.result_controls
1560+
if return_referrals && pdu.result_code == 10
1561+
if block_given?
1562+
se = Net::LDAP::Entry.new
1563+
se[:search_referrals] = (pdu.search_referrals || [])
1564+
yield se
1565+
end
15561566
end
1567+
break
1568+
else
1569+
raise Net::LDAP::LdapError, "invalid response-type in search: #{pdu.app_tag}"
15571570
end
1558-
break
1559-
else
1560-
raise Net::LDAP::LdapError, "invalid response-type in search: #{pdu.app_tag}"
15611571
end
1562-
end
15631572

1564-
# When we get here, we have seen a type-5 response. If there is no
1565-
# error AND there is an RFC-2696 cookie, then query again for the next
1566-
# page of results. If not, we're done. Don't screw this up or we'll
1567-
# break every search we do.
1568-
#
1569-
# Noticed 02Sep06, look at the read_ber call in this loop, shouldn't
1570-
# that have a parameter of AsnSyntax? Does this just accidentally
1571-
# work? According to RFC-2696, the value expected in this position is
1572-
# of type OCTET STRING, covered in the default syntax supported by
1573-
# read_ber, so I guess we're ok.
1574-
more_pages = false
1575-
if result_pdu.result_code == 0 and controls
1576-
controls.each do |c|
1577-
if c.oid == Net::LDAP::LDAPControls::PAGED_RESULTS
1578-
# just in case some bogus server sends us more than 1 of these.
1579-
more_pages = false
1580-
if c.value and c.value.length > 0
1581-
cookie = c.value.read_ber[1]
1582-
if cookie and cookie.length > 0
1583-
rfc2696_cookie[1] = cookie
1584-
more_pages = true
1573+
# count number of pages of results
1574+
payload[:page_count] ||= 0
1575+
payload[:page_count] += 1
1576+
1577+
# When we get here, we have seen a type-5 response. If there is no
1578+
# error AND there is an RFC-2696 cookie, then query again for the next
1579+
# page of results. If not, we're done. Don't screw this up or we'll
1580+
# break every search we do.
1581+
#
1582+
# Noticed 02Sep06, look at the read_ber call in this loop, shouldn't
1583+
# that have a parameter of AsnSyntax? Does this just accidentally
1584+
# work? According to RFC-2696, the value expected in this position is
1585+
# of type OCTET STRING, covered in the default syntax supported by
1586+
# read_ber, so I guess we're ok.
1587+
more_pages = false
1588+
if result_pdu.result_code == 0 and controls
1589+
controls.each do |c|
1590+
if c.oid == Net::LDAP::LDAPControls::PAGED_RESULTS
1591+
# just in case some bogus server sends us more than 1 of these.
1592+
more_pages = false
1593+
if c.value and c.value.length > 0
1594+
cookie = c.value.read_ber[1]
1595+
if cookie and cookie.length > 0
1596+
rfc2696_cookie[1] = cookie
1597+
more_pages = true
1598+
end
15851599
end
15861600
end
15871601
end
15881602
end
1589-
end
15901603

1591-
break unless more_pages
1592-
} # loop
1604+
break unless more_pages
1605+
end # loop
1606+
1607+
payload[:result_count] = n_results
1608+
end # instrument
15931609

15941610
result_pdu || OpenStruct.new(:status => :failure, :result_code => 1, :message => "Invalid search")
15951611
end

0 commit comments

Comments
 (0)