Correct indentation and format.

This commit is contained in:
emiel 2009-02-27 22:43:21 +00:00
parent 2835ecd82d
commit ec47390431

View file

@ -2,7 +2,6 @@
# #
# LDAP PDU support classes # LDAP PDU support classes
# #
#
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# #
# Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved. # Copyright (C) 2006 by Francis Cianfrocca. All Rights Reserved.
@ -24,255 +23,236 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# #
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
#
module Net module Net
class LdapPduError < StandardError; end
class LdapPduError < StandardError; end class LdapPdu
BindRequest = 0
BindResult = 1
UnbindRequest = 2
SearchRequest = 3
SearchReturnedData = 4
SearchResult = 5
ModifyResponse = 7
AddResponse = 9
DeleteResponse = 11
ModifyRDNResponse = 13
SearchResultReferral = 19
ExtendedRequest = 23
ExtendedResponse = 24
class LdapPdu attr_reader :msg_id, :app_tag
attr_reader :search_dn, :search_attributes, :search_entry
attr_reader :search_referrals
attr_reader :search_parameters, :bind_parameters
BindRequest = 0 # An LDAP PDU always looks like a BerSequence with
BindResult = 1 # at least two elements: an integer (message-id number), and
UnbindRequest = 2 # an application-specific sequence.
SearchRequest = 3 # Some LDAPv3 packets also include an optional
SearchReturnedData = 4 # third element, which is a sequence of "controls"
SearchResult = 5 # (See RFC 2251, section 4.1.12).
ModifyResponse = 7 # The application-specific tag in the sequence tells
AddResponse = 9 # us what kind of packet it is, and each kind has its
DeleteResponse = 11 # own format, defined in RFC-1777.
ModifyRDNResponse = 13 # Observe that many clients (such as ldapsearch)
SearchResultReferral = 19 # do not necessarily enforce the expected application
ExtendedRequest = 23 # tags on received protocol packets. This implementation
ExtendedResponse = 24 # does interpret the RFC strictly in this regard, and
# it remains to be seen whether there are servers out
# there that will not work well with our approach.
#
# Added a controls-processor to SearchResult.
# Didn't add it everywhere because it just _feels_
# like it will need to be refactored.
#
def initialize ber_object
begin
@msg_id = ber_object[0].to_i
# Modified 25Nov06. We want to "un-decorate" the ber-identifier
# of the incoming packet. Originally we did this by subtracting 0x60,
# which ASSUMES the identifier is a constructed app-specific value.
# But at least one value (UnbindRequest) is app-specific primitive.
# So it makes more sense just to grab the bottom five bits.
#@app_tag = ber_object[1].ber_identifier - 0x60
@app_tag = ber_object[1].ber_identifier & 31
@ldap_controls = []
rescue
# any error becomes a data-format error
raise LdapPduError.new( "ldap-pdu format error" )
end
attr_reader :msg_id, :app_tag case @app_tag
attr_reader :search_dn, :search_attributes, :search_entry when BindResult
attr_reader :search_referrals parse_bind_response ber_object[1]
attr_reader :search_parameters, :bind_parameters when SearchReturnedData
parse_search_return ber_object[1]
when SearchResultReferral
parse_search_referral ber_object[1]
when SearchResult
parse_ldap_result ber_object[1]
parse_controls(ber_object[2]) if ber_object[2]
when ModifyResponse
parse_ldap_result ber_object[1]
when AddResponse
parse_ldap_result ber_object[1]
when DeleteResponse
parse_ldap_result ber_object[1]
when ModifyRDNResponse
parse_ldap_result ber_object[1]
when SearchRequest
parse_ldap_search_request ber_object[1]
when BindRequest
parse_bind_request ber_object[1]
when UnbindRequest
parse_unbind_request ber_object[1]
when ExtendedResponse
parse_ldap_result ber_object[1]
else
raise LdapPduError.new( "unknown pdu-type: #{@app_tag}" )
end
end
# # Returns a hash which (usually) defines the members :resultCode, :errorMessage, and :matchedDN.
# initialize # These values come directly from an LDAP response packet returned by the remote peer.
# An LDAP PDU always looks like a BerSequence with # See #result_code for a sugaring.
# at least two elements: an integer (message-id number), and #
# an application-specific sequence. def result
# Some LDAPv3 packets also include an optional @ldap_result || {}
# third element, which is a sequence of "controls" end
# (See RFC 2251, section 4.1.12).
# The application-specific tag in the sequence tells
# us what kind of packet it is, and each kind has its
# own format, defined in RFC-1777.
# Observe that many clients (such as ldapsearch)
# do not necessarily enforce the expected application
# tags on received protocol packets. This implementation
# does interpret the RFC strictly in this regard, and
# it remains to be seen whether there are servers out
# there that will not work well with our approach.
#
# Added a controls-processor to SearchResult.
# Didn't add it everywhere because it just _feels_
# like it will need to be refactored.
#
def initialize ber_object
begin
@msg_id = ber_object[0].to_i
# Modified 25Nov06. We want to "un-decorate" the ber-identifier
# of the incoming packet. Originally we did this by subtracting 0x60,
# which ASSUMES the identifier is a constructed app-specific value.
# But at least one value (UnbindRequest) is app-specific primitive.
# So it makes more sense just to grab the bottom five bits.
#@app_tag = ber_object[1].ber_identifier - 0x60
@app_tag = ber_object[1].ber_identifier & 31
@ldap_controls = []
rescue
# any error becomes a data-format error
raise LdapPduError.new( "ldap-pdu format error" )
end
case @app_tag # This returns an LDAP result code taken from the PDU,
when BindResult # but it will be nil if there wasn't a result code.
parse_bind_response ber_object[1] # That can easily happen depending on the type of packet.
when SearchReturnedData #
parse_search_return ber_object[1] def result_code code = :resultCode
when SearchResultReferral @ldap_result and @ldap_result[code]
parse_search_referral ber_object[1] end
when SearchResult
parse_ldap_result ber_object[1]
parse_controls(ber_object[2]) if ber_object[2]
when ModifyResponse
parse_ldap_result ber_object[1]
when AddResponse
parse_ldap_result ber_object[1]
when DeleteResponse
parse_ldap_result ber_object[1]
when ModifyRDNResponse
parse_ldap_result ber_object[1]
when SearchRequest
parse_ldap_search_request ber_object[1]
when BindRequest
parse_bind_request ber_object[1]
when UnbindRequest
parse_unbind_request ber_object[1]
when ExtendedResponse
parse_ldap_result ber_object[1]
else
raise LdapPduError.new( "unknown pdu-type: #{@app_tag}" )
end
end
# Returns a hash which (usually) defines the members :resultCode, :errorMessage, and :matchedDN. # Return RFC-2251 Controls if any.
# These values come directly from an LDAP response packet returned by the remote peer. # Messy. Does this functionality belong somewhere else?
# See #result_code for a sugaring. def result_controls
# @ldap_controls
def result end
@ldap_result || {}
end
# # Return serverSaslCreds, which are only present in BindResponse packets.
# result_code # Messy. Does this functionality belong somewhere else?
# This returns an LDAP result code taken from the PDU, # We ought to refactor the accessors of this class before they get any kludgier.
# but it will be nil if there wasn't a result code. def result_server_sasl_creds
# That can easily happen depending on the type of packet. @ldap_result && @ldap_result[:serverSaslCreds]
# end
def result_code code = :resultCode
@ldap_result and @ldap_result[code]
end
# Return RFC-2251 Controls if any. # parse_ldap_result
# Messy. Does this functionality belong somewhere else? #
def result_controls def parse_ldap_result sequence
@ldap_controls sequence.length >= 3 or raise LdapPduError
end @ldap_result = {:resultCode => sequence[0], :matchedDN => sequence[1], :errorMessage => sequence[2]}
end
# Return serverSaslCreds, which are only present in BindResponse packets. private :parse_ldap_result
# Messy. Does this functionality belong somewhere else?
# We ought to refactor the accessors of this class before they get any kludgier.
def result_server_sasl_creds
@ldap_result && @ldap_result[:serverSaslCreds]
end
# # A Bind Response may have an additional field, ID [7], serverSaslCreds, per RFC 2251 pgh 4.2.3.
# parse_ldap_result #
# def parse_bind_response sequence
def parse_ldap_result sequence sequence.length >= 3 or raise LdapPduError
sequence.length >= 3 or raise LdapPduError @ldap_result = {:resultCode => sequence[0], :matchedDN => sequence[1], :errorMessage => sequence[2]}
@ldap_result = {:resultCode => sequence[0], :matchedDN => sequence[1], :errorMessage => sequence[2]} @ldap_result[:serverSaslCreds] = sequence[3] if sequence.length >= 4
end @ldap_result
private :parse_ldap_result end
# private :parse_bind_response
# parse_bind_response
# A Bind Response may have an additional field, ID [7], serverSaslCreds, per RFC 2251 pgh 4.2.3.
#
def parse_bind_response sequence
sequence.length >= 3 or raise LdapPduError
@ldap_result = {:resultCode => sequence[0], :matchedDN => sequence[1], :errorMessage => sequence[2]}
@ldap_result[:serverSaslCreds] = sequence[3] if sequence.length >= 4
@ldap_result
end
private :parse_bind_response
# # Definition from RFC 1777 (we're handling application-4 here)
# parse_search_return #
# Definition from RFC 1777 (we're handling application-4 here) # Search Response ::=
# # CHOICE {
# Search Response ::= # entry [APPLICATION 4] SEQUENCE {
# CHOICE { # objectName LDAPDN,
# entry [APPLICATION 4] SEQUENCE { # attributes SEQUENCE OF SEQUENCE {
# objectName LDAPDN, # AttributeType,
# attributes SEQUENCE OF SEQUENCE { # SET OF AttributeValue
# AttributeType, # }
# SET OF AttributeValue # },
# } # resultCode [APPLICATION 5] LDAPResult
# }, # }
# resultCode [APPLICATION 5] LDAPResult #
# } # We concoct a search response that is a hash of the returned attribute values.
# # NOW OBSERVE CAREFULLY: WE ARE DOWNCASING THE RETURNED ATTRIBUTE NAMES.
# We concoct a search response that is a hash of the returned attribute values. # This is to make them more predictable for user programs, but it
# NOW OBSERVE CAREFULLY: WE ARE DOWNCASING THE RETURNED ATTRIBUTE NAMES. # may not be a good idea. Maybe this should be configurable.
# This is to make them more predictable for user programs, but it # ALTERNATE IMPLEMENTATION: In addition to @search_dn and @search_attributes,
# may not be a good idea. Maybe this should be configurable. # we also return @search_entry, which is an LDAP::Entry object.
# ALTERNATE IMPLEMENTATION: In addition to @search_dn and @search_attributes, # If that works out well, then we'll remove the first two.
# we also return @search_entry, which is an LDAP::Entry object. #
# If that works out well, then we'll remove the first two. # Provisionally removed obsolete search_attributes and search_dn, 04May06.
# #
# Provisionally removed obsolete search_attributes and search_dn, 04May06. def parse_search_return sequence
# sequence.length >= 2 or raise LdapPduError
def parse_search_return sequence @search_entry = LDAP::Entry.new( sequence[0] )
sequence.length >= 2 or raise LdapPduError sequence[1].each {|seq|
@search_entry = LDAP::Entry.new( sequence[0] ) @search_entry[seq[0]] = seq[1]
sequence[1].each {|seq| }
@search_entry[seq[0]] = seq[1] end
}
end
# # A search referral is a sequence of one or more LDAP URIs.
# A search referral is a sequence of one or more LDAP URIs. # Any number of search-referral replies can be returned by the server, interspersed
# Any number of search-referral replies can be returned by the server, interspersed # with normal replies in any order.
# with normal replies in any order. # Until I can think of a better way to do this, we'll return the referrals as an array.
# Until I can think of a better way to do this, we'll return the referrals as an array. # It'll be up to higher-level handlers to expose something reasonable to the client.
# It'll be up to higher-level handlers to expose something reasonable to the client. def parse_search_referral uris
def parse_search_referral uris @search_referrals = uris
@search_referrals = uris end
end
# Per RFC 2251, an LDAP "control" is a sequence of tuples, each consisting
# of an OID, a boolean criticality flag defaulting FALSE, and an OPTIONAL
# Octet String. If only two fields are given, the second one may be
# either criticality or data, since criticality has a default value.
# Someday we may want to come back here and add support for some of
# more-widely used controls. RFC-2696 is a good example.
#
def parse_controls sequence
@ldap_controls = sequence.map do |control|
o = OpenStruct.new
o.oid,o.criticality,o.value = control[0],control[1],control[2]
if o.criticality and o.criticality.is_a?(String)
o.value = o.criticality
o.criticality = false
end
o
end
end
# Per RFC 2251, an LDAP "control" is a sequence of tuples, each consisting private :parse_controls
# of an OID, a boolean criticality flag defaulting FALSE, and an OPTIONAL
# Octet String. If only two fields are given, the second one may be
# either criticality or data, since criticality has a default value.
# Someday we may want to come back here and add support for some of
# more-widely used controls. RFC-2696 is a good example.
#
def parse_controls sequence
@ldap_controls = sequence.map do |control|
o = OpenStruct.new
o.oid,o.criticality,o.value = control[0],control[1],control[2]
if o.criticality and o.criticality.is_a?(String)
o.value = o.criticality
o.criticality = false
end
o
end
end
private :parse_controls
# (provisional, must document)
def parse_ldap_search_request sequence
s = OpenStruct.new
s.base_object,
s.scope,
s.deref_aliases,
s.size_limit,
s.time_limit,
s.types_only,
s.filter,
s.attributes = sequence
@search_parameters = s
end
# (provisional, must document) # (provisional, must document)
def parse_ldap_search_request sequence def parse_bind_request sequence
s = OpenStruct.new s = OpenStruct.new
s.base_object, s.version,
s.scope, s.name,
s.deref_aliases, s.authentication = sequence
s.size_limit, @bind_parameters = s
s.time_limit, end
s.types_only,
s.filter,
s.attributes = sequence
@search_parameters = s
end
# (provisional, must document)
def parse_bind_request sequence
s = OpenStruct.new
s.version,
s.name,
s.authentication = sequence
@bind_parameters = s
end
# (provisional, must document)
# UnbindRequest has no content so this is a no-op.
def parse_unbind_request sequence
end
end
# (provisional, must document)
# UnbindRequest has no content so this is a no-op.
def parse_unbind_request sequence
end
end
end # module Net end # module Net