lib/net/ldap.rb in net-ldap-0.7.0 vs lib/net/ldap.rb in net-ldap-0.8.0
- old
+ new
@@ -21,10 +21,11 @@
require 'net/ldap/pdu'
require 'net/ldap/filter'
require 'net/ldap/dataset'
require 'net/ldap/password'
require 'net/ldap/entry'
+require 'net/ldap/instrumentation'
require 'net/ldap/version'
# == Quick-start for the Impatient
# === Quick Example of a user-authentication against an LDAP directory:
#
@@ -240,10 +241,11 @@
# operation (typically binding first) and then disconnect from the server.
# The exception is Net::LDAP#open, which makes a connection to the server
# and then keeps it open while it executes a user-supplied block.
# Net::LDAP#open closes the connection on completion of the block.
class Net::LDAP
+ include Net::LDAP::Instrumentation
class LdapError < StandardError; end
SearchScope_BaseObject = 0
SearchScope_SingleLevel = 1
@@ -254,11 +256,11 @@
DerefAliases_Never = 0
DerefAliases_Search = 1
DerefAliases_Find = 2
DerefAliases_Always = 3
DerefAliasesArray = [ DerefAliases_Never, DerefAliases_Search, DerefAliases_Find, DerefAliases_Always ]
-
+
primitive = { 2 => :null } # UnbindRequest body
constructed = {
0 => :array, # BindRequest
1 => :array, # BindResponse
2 => :array, # UnbindRequest
@@ -381,10 +383,12 @@
# specifying the Hash {:method => :simple_tls}. There is a fairly large
# range of potential values that may be given for this parameter. See
# #encryption for details.
# * :force_no_page => Set to true to prevent paged results even if your
# server says it supports them. This is a fix for MS Active Directory
+ # * :instrumentation_service => An object responsible for instrumenting
+ # operations, compatible with ActiveSupport::Notifications' public API.
#
# Instantiating a Net::LDAP object does <i>not</i> result in network
# traffic to the LDAP server. It simply stores the connection and binding
# parameters in the object.
def initialize(args = {})
@@ -398,10 +402,12 @@
if pr = @auth[:password] and pr.respond_to?(:call)
@auth[:password] = pr.call
end
+ @instrumentation_service = args[:instrumentation_service]
+
# This variable is only set when we are created with LDAP::open. All of
# our internal methods will connect using it, or else they will create
# their own.
@open_connection = nil
end
@@ -569,20 +575,25 @@
# anything with the bind results. We then pass self to the caller's
# block, where he will execute his LDAP operations. Of course they will
# all generate auth failures if the bind was unsuccessful.
raise Net::LDAP::LdapError, "Open already in progress" if @open_connection
- begin
- @open_connection = Net::LDAP::Connection.new(:host => @host,
- :port => @port,
- :encryption =>
- @encryption)
- @open_connection.bind(@auth)
- yield self
- ensure
- @open_connection.close if @open_connection
- @open_connection = nil
+ instrument "open.net_ldap" do |payload|
+ begin
+ @open_connection =
+ Net::LDAP::Connection.new \
+ :host => @host,
+ :port => @port,
+ :encryption => @encryption,
+ :instrumentation_service => @instrumentation_service
+ payload[:connection] = @open_connection
+ payload[:bind] = @open_connection.bind(@auth)
+ yield self
+ ensure
+ @open_connection.close if @open_connection
+ @open_connection = nil
+ end
end
end
# Searches the LDAP directory for directory entries. Takes a hash argument
# with parameters. Supported parameters include:
@@ -639,34 +650,39 @@
args[:base] ||= @base
return_result_set = args[:return_result] != false
result_set = return_result_set ? [] : nil
- if @open_connection
- @result = @open_connection.search(args) { |entry|
- result_set << entry if result_set
- yield entry if block_given?
- }
- else
- begin
- conn = Net::LDAP::Connection.new(:host => @host, :port => @port,
- :encryption => @encryption)
- if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
- @result = conn.search(args) { |entry|
- result_set << entry if result_set
- yield entry if block_given?
- }
+ instrument "search.net_ldap", args do |payload|
+ if @open_connection
+ @result = @open_connection.search(args) { |entry|
+ result_set << entry if result_set
+ yield entry if block_given?
+ }
+ else
+ begin
+ conn = Net::LDAP::Connection.new \
+ :host => @host,
+ :port => @port,
+ :encryption => @encryption,
+ :instrumentation_service => @instrumentation_service
+ if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
+ @result = conn.search(args) { |entry|
+ result_set << entry if result_set
+ yield entry if block_given?
+ }
+ end
+ ensure
+ conn.close if conn
end
- ensure
- conn.close if conn
end
- end
- if return_result_set
- (!@result.nil? && @result.result_code == 0) ? result_set : nil
- else
- @result.success?
+ if return_result_set
+ (!@result.nil? && @result.result_code == 0) ? result_set : nil
+ else
+ @result.success?
+ end
end
end
# #bind connects to an LDAP server and requests authentication based on
# the <tt>:auth</tt> parameter passed to #open or #new. It takes no
@@ -724,23 +740,30 @@
# calling #bind. Otherwise, you'll just re-authenticate the previous user!
# (You don't need to re-set the values of #host and #port.) As noted in
# the documentation for #auth, the password parameter can be a Ruby Proc
# instead of a String.
def bind(auth = @auth)
- if @open_connection
- @result = @open_connection.bind(auth)
- else
- begin
- conn = Connection.new(:host => @host, :port => @port,
- :encryption => @encryption)
- @result = conn.bind(auth)
- ensure
- conn.close if conn
+ instrument "bind.net_ldap" do |payload|
+ if @open_connection
+ payload[:connection] = @open_connection
+ payload[:bind] = @result = @open_connection.bind(auth)
+ else
+ begin
+ conn = Connection.new \
+ :host => @host,
+ :port => @port,
+ :encryption => @encryption,
+ :instrumentation_service => @instrumentation_service
+ payload[:connection] = conn
+ payload[:bind] = @result = conn.bind(auth)
+ ensure
+ conn.close if conn
+ end
end
- end
- @result.success?
+ @result.success?
+ end
end
# #bind_as is for testing authentication credentials.
#
# As described under #bind, most LDAP servers require that you supply a
@@ -824,25 +847,30 @@
# }
# Net::LDAP.open(:host => host) do |ldap|
# ldap.add(:dn => dn, :attributes => attr)
# end
def add(args)
- if @open_connection
- @result = @open_connection.add(args)
- else
- @result = 0
- begin
- conn = Connection.new(:host => @host, :port => @port,
- :encryption => @encryption)
- if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
- @result = conn.add(args)
+ instrument "add.net_ldap", args do |payload|
+ if @open_connection
+ @result = @open_connection.add(args)
+ else
+ @result = 0
+ begin
+ conn = Connection.new \
+ :host => @host,
+ :port => @port,
+ :encryption => @encryption,
+ :instrumentation_service => @instrumentation_service
+ if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
+ @result = conn.add(args)
+ end
+ ensure
+ conn.close if conn
end
- ensure
- conn.close if conn
end
+ @result.success?
end
- @result.success?
end
# Modifies the attribute values of a particular entry on the LDAP
# directory. Takes a hash with arguments. Supported arguments are:
# :dn :: (the full DN of the entry whose attributes are to be modified)
@@ -856,11 +884,11 @@
# provide simpler interfaces to this functionality.
#
# The LDAP protocol provides a full and well thought-out set of operations
# for changing the values of attributes, but they are necessarily somewhat
# complex and not always intuitive. If these instructions are confusing or
- # incomplete, please send us email or create a bug report on rubyforge.
+ # incomplete, please send us email or create an issue on GitHub.
#
# The :operations parameter to #modify takes an array of
# operation-descriptors. Each individual operation is specified in one
# element of the array, and most LDAP servers will attempt to perform the
# operations in order.
@@ -922,26 +950,31 @@
# semantics, in which the several operations contained in a single #modify
# call are not interleaved with other modification-requests received
# simultaneously by the server. It bears repeating that this concurrency
# does _not_ imply transactional atomicity, which LDAP does not provide.
def modify(args)
- if @open_connection
- @result = @open_connection.modify(args)
- else
- @result = 0
- begin
- conn = Connection.new(:host => @host, :port => @port,
- :encryption => @encryption)
- if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
- @result = conn.modify(args)
+ instrument "modify.net_ldap", args do |payload|
+ if @open_connection
+ @result = @open_connection.modify(args)
+ else
+ @result = 0
+ begin
+ conn = Connection.new \
+ :host => @host,
+ :port => @port,
+ :encryption => @encryption,
+ :instrumentation_service => @instrumentation_service
+ if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
+ @result = conn.modify(args)
+ end
+ ensure
+ conn.close if conn
end
- ensure
- conn.close if conn
end
- end
- @result.success?
+ @result.success?
+ end
end
# Add a value to an attribute. Takes the full DN of the entry to modify,
# the name (Symbol or String) of the attribute, and the value (String or
# Array). If the attribute does not exist (and there are no schema
@@ -994,25 +1027,30 @@
# Rename an entry on the remote DIS by changing the last RDN of its DN.
#
# _Documentation_ _stub_
def rename(args)
- if @open_connection
- @result = @open_connection.rename(args)
- else
- @result = 0
- begin
- conn = Connection.new(:host => @host, :port => @port,
- :encryption => @encryption)
- if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
- @result = conn.rename(args)
+ instrument "rename.net_ldap", args do |payload|
+ if @open_connection
+ @result = @open_connection.rename(args)
+ else
+ @result = 0
+ begin
+ conn = Connection.new \
+ :host => @host,
+ :port => @port,
+ :encryption => @encryption,
+ :instrumentation_service => @instrumentation_service
+ if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
+ @result = conn.rename(args)
+ end
+ ensure
+ conn.close if conn
end
- ensure
- conn.close if conn
end
+ @result.success?
end
- @result.success?
end
alias_method :modify_rdn, :rename
# Delete an entry from the LDAP directory. Takes a hash of arguments. The
# only supported argument is :dn, which must give the complete DN of the
@@ -1022,25 +1060,30 @@
# status information is available by calling #get_operation_result.
#
# dn = "mail=deleteme@example.com, ou=people, dc=example, dc=com"
# ldap.delete :dn => dn
def delete(args)
- if @open_connection
- @result = @open_connection.delete(args)
- else
- @result = 0
- begin
- conn = Connection.new(:host => @host, :port => @port,
- :encryption => @encryption)
- if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
- @result = conn.delete(args)
+ instrument "delete.net_ldap", args do |payload|
+ if @open_connection
+ @result = @open_connection.delete(args)
+ else
+ @result = 0
+ begin
+ conn = Connection.new \
+ :host => @host,
+ :port => @port,
+ :encryption => @encryption,
+ :instrumentation_service => @instrumentation_service
+ if (@result = conn.bind(args[:auth] || @auth)).result_code == 0
+ @result = conn.delete(args)
+ end
+ ensure
+ conn.close
end
- ensure
- conn.close
end
+ @result.success?
end
- @result.success?
end
# Delete an entry from the LDAP directory along with all subordinate entries.
# the regular delete method will fail to delete an entry if it has subordinate
# entries. This method sends an extra control code to tell the LDAP server
@@ -1123,24 +1166,28 @@
# MUST refactor the root_dse call out.
#++
def paged_searches_supported?
# active directory returns that it supports paged results. However
# it returns binary data in the rfc2696_cookie which throws an
- # encoding exception breaking searching.
+ # encoding exception breaking searching.
return false if @force_no_page
@server_caps ||= search_root_dse
@server_caps[:supportedcontrol].include?(Net::LDAP::LDAPControls::PAGED_RESULTS)
end
end # class LDAP
# This is a private class used internally by the library. It should not
# be called by user code.
class Net::LDAP::Connection #:nodoc:
+ include Net::LDAP::Instrumentation
+
LdapVersion = 3
MaxSaslChallenges = 10
def initialize(server)
+ @instrumentation_service = server[:instrumentation_service]
+
begin
@conn = TCPSocket.new(server[:host], server[:port])
rescue SocketError
raise Net::LDAP::LdapError, "No such address or other socket error."
rescue Errno::ECONNREFUSED
@@ -1216,12 +1263,12 @@
# go here.
when :start_tls
msgid = next_msgid.to_ber
request = [Net::LDAP::StartTlsOid.to_ber_contextspecific(0)].to_ber_appsequence(Net::LDAP::PDU::ExtendedRequest)
request_pkt = [msgid, request].to_ber_sequence
- @conn.write request_pkt
- be = @conn.read_ber(Net::LDAP::AsnSyntax)
+ write request_pkt
+ be = read
raise Net::LDAP::LdapError, "no start_tls result" if be.nil?
pdu = Net::LDAP::PDU.new(be)
raise Net::LDAP::LdapError, "no start_tls result" if pdu.nil?
if pdu.result_code.zero?
@conn = self.class.wrap_with_ssl(@conn)
@@ -1241,25 +1288,55 @@
def close
@conn.close
@conn = nil
end
+ # Internal: Reads and parses data from the configured connection.
+ #
+ # - syntax: the BER syntax to use to parse the read data with
+ #
+ # Returns basic BER objects.
+ def read(syntax = Net::LDAP::AsnSyntax)
+ instrument "read.net_ldap_connection", :syntax => syntax do |payload|
+ @conn.read_ber(syntax) do |id, content_length|
+ payload[:object_type_id] = id
+ payload[:content_length] = content_length
+ end
+ end
+ end
+ private :read
+
+ # Internal: Writes the given packet to the configured connection.
+ #
+ # - packet: the BER data packet to write on the socket.
+ #
+ # Returns the return value from writing to the connection, which in some
+ # cases is the Integer number of bytes written to the socket.
+ def write(packet)
+ instrument "write.net_ldap_connection" do |payload|
+ payload[:content_length] = @conn.write(packet)
+ end
+ end
+ private :write
+
def next_msgid
@msgid ||= 0
@msgid += 1
end
def bind(auth)
- meth = auth[:method]
- if [:simple, :anonymous, :anon].include?(meth)
- bind_simple auth
- elsif meth == :sasl
- bind_sasl(auth)
- elsif meth == :gss_spnego
- bind_gss_spnego(auth)
- else
- raise Net::LDAP::LdapError, "Unsupported auth method (#{meth})"
+ instrument "bind.net_ldap_connection" do |payload|
+ payload[:method] = meth = auth[:method]
+ if [:simple, :anonymous, :anon].include?(meth)
+ bind_simple auth
+ elsif meth == :sasl
+ bind_sasl(auth)
+ elsif meth == :gss_spnego
+ bind_gss_spnego(auth)
+ else
+ raise Net::LDAP::LdapError, "Unsupported auth method (#{meth})"
+ end
end
end
#--
# Implements a simple user/psw authentication. Accessed by calling #bind
@@ -1276,13 +1353,13 @@
msgid = next_msgid.to_ber
request = [LdapVersion.to_ber, user.to_ber,
psw.to_ber_contextspecific(0)].to_ber_appsequence(0)
request_pkt = [msgid, request].to_ber_sequence
- @conn.write request_pkt
+ write request_pkt
- (be = @conn.read_ber(Net::LDAP::AsnSyntax) and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result"
+ (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result"
pdu
end
#--
@@ -1315,13 +1392,13 @@
loop {
msgid = next_msgid.to_ber
sasl = [mech.to_ber, cred.to_ber].to_ber_contextspecific(3)
request = [LdapVersion.to_ber, "".to_ber, sasl].to_ber_appsequence(0)
request_pkt = [msgid, request].to_ber_sequence
- @conn.write request_pkt
+ write request_pkt
- (be = @conn.read_ber(Net::LDAP::AsnSyntax) and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result"
+ (be = read and pdu = Net::LDAP::PDU.new(be)) or raise Net::LDAP::LdapError, "no bind result"
return pdu unless pdu.result_code == 14 # saslBindInProgress
raise Net::LDAP::LdapError, "sasl-challenge overflow" if ((n += 1) > MaxSaslChallenges)
cred = chall.call(pdu.result_server_sasl_creds)
}
@@ -1417,11 +1494,11 @@
sort_control = encode_sort_controls(args.fetch(:sort_controls){ false })
deref = args[:deref] || Net::LDAP::DerefAliases_Never
raise Net::LDAP::LdapError.new( "invalid alias dereferencing value" ) unless Net::LDAP::DerefAliasesArray.include?(deref)
-
+
# An interesting value for the size limit would be close to A/D's
# built-in page limit of 1000 records, but openLDAP newer than version
# 2.2.0 chokes on anything bigger than 126. You get a silent error that
# is easily visible by running slapd in debug mode. Go figure.
#
@@ -1442,114 +1519,131 @@
# doesn't support it. Yuck.
rfc2696_cookie = [126, ""]
result_pdu = nil
n_results = 0
- loop {
- # should collect this into a private helper to clarify the structure
- query_limit = 0
- if sizelimit > 0
- if paged_searches_supported
- query_limit = (((sizelimit - n_results) < 126) ? (sizelimit -
- n_results) : 0)
- else
- query_limit = sizelimit
+ instrument "search.net_ldap_connection",
+ :filter => search_filter,
+ :base => search_base,
+ :scope => scope,
+ :limit => sizelimit,
+ :sort => sort_control,
+ :referrals => return_referrals,
+ :deref => deref,
+ :attributes => search_attributes do |payload|
+ loop do
+ # should collect this into a private helper to clarify the structure
+ query_limit = 0
+ if sizelimit > 0
+ if paged_searches_supported
+ query_limit = (((sizelimit - n_results) < 126) ? (sizelimit -
+ n_results) : 0)
+ else
+ query_limit = sizelimit
+ end
end
- end
- request = [
- search_base.to_ber,
- scope.to_ber_enumerated,
- deref.to_ber_enumerated,
- query_limit.to_ber, # size limit
- 0.to_ber,
- attributes_only.to_ber,
- search_filter.to_ber,
- search_attributes.to_ber_sequence
- ].to_ber_appsequence(3)
+ request = [
+ search_base.to_ber,
+ scope.to_ber_enumerated,
+ deref.to_ber_enumerated,
+ query_limit.to_ber, # size limit
+ 0.to_ber,
+ attributes_only.to_ber,
+ search_filter.to_ber,
+ search_attributes.to_ber_sequence
+ ].to_ber_appsequence(3)
- # rfc2696_cookie sometimes contains binary data from Microsoft Active Directory
- # this breaks when calling to_ber. (Can't force binary data to UTF-8)
- # we have to disable paging (even though server supports it) to get around this...
+ # rfc2696_cookie sometimes contains binary data from Microsoft Active Directory
+ # this breaks when calling to_ber. (Can't force binary data to UTF-8)
+ # we have to disable paging (even though server supports it) to get around this...
- controls = []
- controls <<
- [
- Net::LDAP::LDAPControls::PAGED_RESULTS.to_ber,
- # Criticality MUST be false to interoperate with normal LDAPs.
- false.to_ber,
- rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber
- ].to_ber_sequence if paged_searches_supported
- controls << sort_control if sort_control
- controls = controls.empty? ? nil : controls.to_ber_contextspecific(0)
+ controls = []
+ controls <<
+ [
+ Net::LDAP::LDAPControls::PAGED_RESULTS.to_ber,
+ # Criticality MUST be false to interoperate with normal LDAPs.
+ false.to_ber,
+ rfc2696_cookie.map{ |v| v.to_ber}.to_ber_sequence.to_s.to_ber
+ ].to_ber_sequence if paged_searches_supported
+ controls << sort_control if sort_control
+ controls = controls.empty? ? nil : controls.to_ber_contextspecific(0)
- pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence
- @conn.write pkt
+ pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence
+ write pkt
- result_pdu = nil
- controls = []
+ result_pdu = nil
+ controls = []
- while (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be))
- case pdu.app_tag
- when 4 # search-data
- n_results += 1
- yield pdu.search_entry if block_given?
- when 19 # search-referral
- if return_referrals
- if block_given?
- se = Net::LDAP::Entry.new
- se[:search_referrals] = (pdu.search_referrals || [])
- yield se
+ while (be = read) && (pdu = Net::LDAP::PDU.new(be))
+ case pdu.app_tag
+ when Net::LDAP::PDU::SearchReturnedData
+ n_results += 1
+ yield pdu.search_entry if block_given?
+ when Net::LDAP::PDU::SearchResultReferral
+ if return_referrals
+ if block_given?
+ se = Net::LDAP::Entry.new
+ se[:search_referrals] = (pdu.search_referrals || [])
+ yield se
+ end
end
- end
- when 5 # search-result
- result_pdu = pdu
- controls = pdu.result_controls
- if return_referrals && pdu.result_code == 10
- if block_given?
- se = Net::LDAP::Entry.new
- se[:search_referrals] = (pdu.search_referrals || [])
- yield se
+ when Net::LDAP::PDU::SearchResult
+ result_pdu = pdu
+ controls = pdu.result_controls
+ if return_referrals && pdu.result_code == 10
+ if block_given?
+ se = Net::LDAP::Entry.new
+ se[:search_referrals] = (pdu.search_referrals || [])
+ yield se
+ end
end
+ break
+ else
+ raise Net::LDAP::LdapError, "invalid response-type in search: #{pdu.app_tag}"
end
- break
- else
- raise Net::LDAP::LdapError, "invalid response-type in search: #{pdu.app_tag}"
end
- end
- # When we get here, we have seen a type-5 response. If there is no
- # error AND there is an RFC-2696 cookie, then query again for the next
- # page of results. If not, we're done. Don't screw this up or we'll
- # break every search we do.
- #
- # Noticed 02Sep06, look at the read_ber call in this loop, shouldn't
- # that have a parameter of AsnSyntax? Does this just accidentally
- # work? According to RFC-2696, the value expected in this position is
- # of type OCTET STRING, covered in the default syntax supported by
- # read_ber, so I guess we're ok.
- more_pages = false
- if result_pdu.result_code == 0 and controls
- controls.each do |c|
- if c.oid == Net::LDAP::LDAPControls::PAGED_RESULTS
- # just in case some bogus server sends us more than 1 of these.
- more_pages = false
- if c.value and c.value.length > 0
- cookie = c.value.read_ber[1]
- if cookie and cookie.length > 0
- rfc2696_cookie[1] = cookie
- more_pages = true
+ # count number of pages of results
+ payload[:page_count] ||= 0
+ payload[:page_count] += 1
+
+ # When we get here, we have seen a type-5 response. If there is no
+ # error AND there is an RFC-2696 cookie, then query again for the next
+ # page of results. If not, we're done. Don't screw this up or we'll
+ # break every search we do.
+ #
+ # Noticed 02Sep06, look at the read_ber call in this loop, shouldn't
+ # that have a parameter of AsnSyntax? Does this just accidentally
+ # work? According to RFC-2696, the value expected in this position is
+ # of type OCTET STRING, covered in the default syntax supported by
+ # read_ber, so I guess we're ok.
+ more_pages = false
+ if result_pdu.result_code == 0 and controls
+ controls.each do |c|
+ if c.oid == Net::LDAP::LDAPControls::PAGED_RESULTS
+ # just in case some bogus server sends us more than 1 of these.
+ more_pages = false
+ if c.value and c.value.length > 0
+ cookie = c.value.read_ber[1]
+ if cookie and cookie.length > 0
+ rfc2696_cookie[1] = cookie
+ more_pages = true
+ end
end
end
end
end
- end
- break unless more_pages
- } # loop
+ break unless more_pages
+ end # loop
- result_pdu || OpenStruct.new(:status => :failure, :result_code => 1, :message => "Invalid search")
+ # track total result count
+ payload[:result_count] = n_results
+
+ result_pdu || OpenStruct.new(:status => :failure, :result_code => 1, :message => "Invalid search")
+ end # instrument
end
MODIFY_OPERATIONS = { #:nodoc:
:add => 0,
:delete => 1,
@@ -1582,13 +1676,13 @@
modify_dn = args[:dn] or raise "Unable to modify empty DN"
ops = self.class.modify_ops args[:operations]
request = [ modify_dn.to_ber,
ops.to_ber_sequence ].to_ber_appsequence(6)
pkt = [ next_msgid.to_ber, request ].to_ber_sequence
- @conn.write pkt
+ write pkt
- (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 7) or raise Net::LDAP::LdapError, "response missing or invalid"
+ (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::ModifyResponse) or raise Net::LDAP::LdapError, "response missing or invalid"
pdu
end
#--
@@ -1605,15 +1699,15 @@
add_attrs << [ k.to_s.to_ber, Array(v).map { |m| m.to_ber}.to_ber_set ].to_ber_sequence
}
request = [add_dn.to_ber, add_attrs.to_ber_sequence].to_ber_appsequence(8)
pkt = [next_msgid.to_ber, request].to_ber_sequence
- @conn.write pkt
+ write pkt
- (be = @conn.read_ber(Net::LDAP::AsnSyntax)) &&
+ (be = read) &&
(pdu = Net::LDAP::PDU.new(be)) &&
- (pdu.app_tag == 9) or
+ (pdu.app_tag == Net::LDAP::PDU::AddResponse) or
raise Net::LDAP::LdapError, "response missing or invalid"
pdu
end
@@ -1628,14 +1722,14 @@
request = [old_dn.to_ber, new_rdn.to_ber, delete_attrs.to_ber]
request << new_superior.to_ber_contextspecific(0) unless new_superior == nil
pkt = [next_msgid.to_ber, request.to_ber_appsequence(12)].to_ber_sequence
- @conn.write pkt
+ write pkt
- (be = @conn.read_ber(Net::LDAP::AsnSyntax)) &&
- (pdu = Net::LDAP::PDU.new( be )) && (pdu.app_tag == 13) or
+ (be = read) &&
+ (pdu = Net::LDAP::PDU.new( be )) && (pdu.app_tag == Net::LDAP::PDU::ModifyRDNResponse) or
raise Net::LDAP::LdapError.new( "response missing or invalid" )
pdu
end
@@ -1645,12 +1739,12 @@
def delete(args)
dn = args[:dn] or raise "Unable to delete empty DN"
controls = args.include?(:control_codes) ? args[:control_codes].to_ber_control : nil #use nil so we can compact later
request = dn.to_s.to_ber_application_string(10)
pkt = [next_msgid.to_ber, request, controls].compact.to_ber_sequence
- @conn.write pkt
+ write pkt
- (be = @conn.read_ber(Net::LDAP::AsnSyntax)) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == 11) or raise Net::LDAP::LdapError, "response missing or invalid"
+ (be = read) && (pdu = Net::LDAP::PDU.new(be)) && (pdu.app_tag == Net::LDAP::PDU::DeleteResponse) or raise Net::LDAP::LdapError, "response missing or invalid"
pdu
end
end # class Connection