You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
2.7 KiB
88 lines
2.7 KiB
require 'ldap/server/result'
|
|
|
|
module LDAP
|
|
class Server
|
|
|
|
class Operation
|
|
|
|
# Return true if connection is not authenticated
|
|
|
|
def anonymous?
|
|
@connection.binddn.nil?
|
|
end
|
|
|
|
# Split dn string into its component parts, returning
|
|
# [ {attr=>val}, {attr=>val}, ... ]
|
|
#
|
|
# This is pretty horrible legacy stuff from X500; see RFC2253 for the
|
|
# full gore. It's stupid that the LDAP protocol sends the DN in string
|
|
# form, rather than in ASN1 form (as it does with search filters, for
|
|
# example), even though the DN syntax is defined in terms of ASN1!
|
|
#
|
|
# Attribute names are downcased, but values are not. For any
|
|
# case-insensitive attributes it's up to you to downcase them.
|
|
#
|
|
# Note that only v2 clients should add extra space around the comma.
|
|
# This is accepted, and so is semicolon instead of comma, but the
|
|
# full RFC1779 backwards-compatibility rules (e.g. quoted values)
|
|
# are not implemented.
|
|
#
|
|
# I *think* these functions will work correctly with UTF8-encoded
|
|
# characters, given that a multibyte UTF8 character does not contain
|
|
# the bytes 00-7F and therefore we cannot confuse '\', '+' etc
|
|
|
|
def self.split_dn(dn)
|
|
# convert \\ to \5c, \+ to \2b etc
|
|
dn.gsub!(/\\([ #,+"\\<>;])/) { |match| format "\\%02x", match[1].ord }
|
|
|
|
# Now we know that \\ and \, do not exist, it's safe to split
|
|
parts = dn.split(/\s*[,;]\s*/)
|
|
|
|
parts.collect do |part|
|
|
res = {}
|
|
|
|
# Split each part into attr=val+attr=val
|
|
avs = part.split(/\+/)
|
|
|
|
avs.each do |av|
|
|
# These should all be of form attr=value
|
|
unless av =~ /^([^=]+)=(.*)$/
|
|
raise LDAP::ResultError::ProtocolError, "Bad DN component: #{av}"
|
|
end
|
|
attr, val = $1.downcase, $2
|
|
# Now we can decode those bits
|
|
attr.gsub!(/\\([a-f0-9][a-f0-9])/i) { $1.hex.chr }
|
|
val.gsub!(/\\([a-f0-9][a-f0-9])/i) { $1.hex.chr }
|
|
res[attr] = val
|
|
end
|
|
res
|
|
end
|
|
end
|
|
|
|
# Reverse of split_dn. Join [elements...]
|
|
# where each element can be {attr=>val,...} or [[attr,val],...]
|
|
# or just [attr,val]
|
|
|
|
def self.join_dn(elements)
|
|
dn = ""
|
|
elements.each do |elem|
|
|
av = ""
|
|
elem = [elem] if elem[0].is_a?(String)
|
|
elem.each do |attr,val|
|
|
av << "+" unless av == ""
|
|
|
|
av << attr << "=" <<
|
|
val.sub(/^([# ])/, '\\\\\\1').
|
|
sub(/( )$/, '\\\\\\1').
|
|
gsub(/([,+"\\<>;])/, '\\\\\\1')
|
|
end
|
|
dn << "," unless dn == ""
|
|
dn << av
|
|
end
|
|
dn
|
|
end
|
|
|
|
end # class Operation
|
|
|
|
end # class Server
|
|
end # module LDAP
|